12 Replies Latest reply: Nov 6, 2008 2:01 PM by 807589 RSS

    Calendar and Date objects

    807589
      I've got an application that has many Date objects. We frequently have to do comparisons to see if two Date objects represent the same day. I know that I can use a SiimpleDateFormatter to make a String from a Date. I can compare two of these Strings and determine if they are on the same day.

      I also know that I can make two new Date objects from the milliseconds in a pair of Date objects, and set the hour, minute, seconds and milliseconds to zeros. Then, the compareTo method to see if the two days match. But, both of these seem like a huge overhead when I have to do it a lot. (Although the objects are called Date, the compareTo matches the milliseconds version, and so two Date objects from the same day do not match unless they match to the millisecond. Not what I want.)

      Have I overlooked something that returns a nice int or long "Julian day number" field that is quick?

      If I can assure myself that all of the dates were built with a common TimeZone, could I divide by the milliseconds in a day to get a nice day number?
        • 1. Re: Calendar and Date objects
          807589
          have you tried


          int hour = Calendar.getInstance().get(Calendar.HOUR);
          or
          int day = Calendar.getInstance().get(Calendar.DAY);
          or

          int dayofmonth= Calendar.getInstance().get(Calendar.DAY_OF_MONTH);

          all will return a simple integer for you to compare.
          • 2. Re: Calendar and Date objects
            DrClap
            Are you sure this isn't premature optimization? You said "seem like a huge overhead" but you didn't sound convinced.

            Your proposed hack of dividing by the number of milliseconds in a day sounds good but fails in places which use daylight saving time (because not all days have 24 hours there, one per year has 23 hours and one per year has 25 hours). So using a Calendar object is pretty much mandatory. I don't know whether it's less overhead to set all of the below-day fields to zero or to compare all the day-and-above fields for equality, but I wouldn't think either would be startlingly better.

            Anyway I wouldn't mess with it unless I was sure it needed optimizing.
            • 3. Re: Calendar and Date objects
              807589
              Thanks for the suggestions (both of them).

              The application is a scheduling system. We need to be able to make a Gantt chart in a JTable (actually it is a JTreeTable), and items can get moved around a lot. When we start to draw an item, we can get the millisecond time (day plus time of day) for the start and end. One of the first decisions is how many days (columns) need to be drawn.The events could cross week, month, year boundaries. I realize I need a robust solution. The code runs today, but I wonder if there is an easier / faster way to do this day-oriented date calculation.

              I got my hopes up when I saw the mention of Calendar.DAY, but there is a DAY_OF_MONTH, and DAY_OF_YEAR, DAY_OF_WEEK, but no DAY.

              I'll probably do an experiment to see what kinds of overhead are involved. I'll report back here with the results.
              • 4. Re: Calendar and Date objects
                799716
                DAY as in Calendar.DAY_OF_YEAR ?

                Mayby the getTime() would be helpful?
                • 5. Re: Calendar and Date objects
                  807589
                  Yes, but the DAY_OF_YEAR by itself is incomplete.

                  The Date object's millisecond value is the time since January 1, 1970. What I wanted was a method that returned a value that was 0 on January 1, 1970, 1 on January 2, 1970, etc.
                  Today would be 14189, so an int would be big enough.
                  • 6. Re: Calendar and Date objects
                    807589
                    I've got an application that has many Date objects. We frequently have to do comparisons to see if two Date objects represent the same day.
                    You might want to have a look at the [Joda API|http://joda-time.sourceforge.net/]. Example:
                    import java.util.Date;
                    
                    import org.joda.time.LocalDate;
                    
                    public class JodaDateEqualsDemo {
                    
                         public static void main(String[] args) {
                              Date d1 = new Date();
                              try { Thread.sleep(5); } catch (InterruptedException e) {/* chomp */}
                              Date d2 = new Date();
                              assert !d1.equals(d2);
                              
                              LocalDate date1 = LocalDate.fromDateFields(d1);
                              LocalDate date2 = LocalDate.fromDateFields(d2);
                              assert date1.equals(date2);
                         }
                    
                    }
                    I wonder if there is an easier / faster way to do this day-oriented date calculation.
                    Have a look at that API. For purposes of disclosure, I have nothing to do with that project, other than as a user. I've found it to be exceedingly easy and useful. Not to mention that something very similar to it is planned for Java 7.

                    ~
                    • 7. Re: Calendar and Date objects
                      807589
                      Thanks for that suggestion. I'll look in that package.
                      • 8. Re: Calendar and Date objects
                        807589
                        d.patterson wrote:
                        I got my hopes up when I saw the mention of Calendar.DAY, but there is a DAY_OF_MONTH, and DAY_OF_YEAR, DAY_OF_WEEK, but no DAY.
                        what do you mean? what do you need? Monday to Sunday etc.

                        if so DAY_OF_WEEK will get you this. in int
                        • 9. Re: Calendar and Date objects
                          807589
                          Maybe an example would clear things up.

                          This is a large scheduling application, with a very complex GUI.

                          We find out from a database that an activity runs from December 28, 2008 at 10:31AM to January 2, 2009 at 11:45AM.

                          The first question after we have converted each date/time pair to a Date object is: "On how many days does this activity take place?" In this case it is 6 days Dec 28, Dec 29, Dec 30, Dec 31, Jan 1, and Jan2. This will be displayed in a JTable with 6 columns. The ideal (at least to me) solution would be to get a day number as described above for the start and end, and know that (end_day - start_day + 1) columns are required, and we can write a for loop to go from the start day to the end day. If we use a semi-day value of the (year*1000 +DAY_OF_YEAR) we have a unique number, but it is useless for determining how many columns are needed in a table. The comparison between 2008363 and 2009002 does not produce a usable result.

                          But, there are related operations as part of a more significant activity. We usually have to decide how many days (columns) does it take to display a group of activities. At this level, we don't care what time of days are involved.

                          This application is on the desktop of multiple schedulers who will move activities around all day long. We need to be as efficient as possible, since some of the other things are very compute intensive.

                          In parts of the application we are very much concerned about time of day, (for example, the custom table cell renderer paints a stripe across the cell of each table cell with a length proportional to the time of day start and end) but in other parts, the day is the main concern.

                          I was bothered by the number of Date to Calendar to String conversions being done, and knowing that Date-to-Calendar is not simple due to time zone issues. I also know that Calendar-to-String conversions are not simple since the SimpleDateFormatter has to dynamically interpret a formatting string.

                          It looks like I'm just stuck with the way it is, unless the alternative date/time implementation is used. That looks a bit promising.
                          • 10. Re: Calendar and Date objects
                            DrClap
                            I don't really think you have a performance problem, no matter what you do. (Within reason of course.) It's just clunky trying to implement dates (as opposed to timestamps) with Calendar objects, but it can be done.

                            In your example, I would start with the activity start time (2008-12-28 10:31) and create a Calendar object with that value and time component set to zero. That represents Dec 28. Then I would add one calendar day repeatedly to that until I got something that was later than the activity end date. That would represent Jan 3. All of the days I got in that loop, except the one that made it exit, would become column headings. That sounds like a lot, but it's really a trivial amount of processing.

                            But I agree with yawmark, the Joda date and time classes take care of a lot of the abstraction you need in that application. You need something to represent the entire day December 28, 2008, for example. Sure you can use a Calendar object for that, but then the semantics of that abstraction have to be implemented in your code.
                            • 11. Re: Calendar and Date objects
                              807589
                              Thanks. Some code is just ugly, but at least it works.

                              Our solution is much as you describe.
                              • 12. Re: Calendar and Date objects
                                807589
                                DrClap wrote:
                                the Joda date and time classes take care of a lot of the abstraction you need in that application. You need something to represent the entire day December 28, 2008, for example. Sure you can use a Calendar object for that, but then the semantics of that abstraction have to be implemented in your code.
                                Yes, indeed.
                                d.patterson wrote:
                                The first question after we have converted each date/time pair to a Date object is: "On how many days does this activity take place?" In this case it is 6 days Dec 28, Dec 29, Dec 30, Dec 31, Jan 1, and Jan2.
                                ...
                                It looks like I'm just stuck with the way it is, unless the alternative date/time implementation is used. That looks a bit promising.
                                Example:
                                import org.joda.time.DateTime;
                                import org.joda.time.Period;
                                
                                public class JodaDateRangeDemo {
                                
                                     public static void main(String[] args) {
                                          DateTime start = new DateTime("2008-12-28T10:31:00");
                                          DateTime end = new DateTime("2009-01-02T11:45:00");
                                          Period period = new Period(start, end);
                                          assert 6 == period.getDays();
                                          
                                          // if you need each day...
                                          while (!start.isAfter(end)) {
                                               System.out.println(start);
                                               start = start.plusDays(1);
                                          }
                                     }
                                }
                                ~