This week's book giveaway is in the Design and Architecture forum. We're giving away four copies of Communication Patterns: A Guide for Developers and Architects and have Jacqui Read on-line! See this thread for details.
How about using Timestamp.getTime() to get the number of ms, subtracting the two for the difference, and then dividing the difference by 24 * 60 ^ 60 * 1000 to get days?
I wrote a class to calculate differences in Dates. Feel free to try it and use it.
It's pretty simple to use. Assuming you have two Date objects and you want to find out the difference in days, for example: TimeSpan ts = TimeSpan.subtract(d1, d2); System.out.println(ts.getDays()); Suggestions for improvements are welcome. [ January 30, 2003: Message edited by: Thomas Paul ]
Cool. Suggestions for improvements are welcome. OK, you asked for it. Inside getInstance(), I think return new TimeSpan(value); should be return new TimeSpan(time); Other stuff: It looks like someone's using a tool which imports javadoc comments from overridden methods. Unfortunately they aren't always correct for the new class. (E.g. the toString() method.) And even if they're correct, they're often dead weight - there's no need to repeat the general contract of equals() and hashCode(); javadoc will provide a link to the overridden methods anyway. In general, the current comments tell you nothing that's not apparent from reading the method names. My feeling is that when that's the case, they might as well be deleted for readability, or replaced. The javadoc should probably explain the difference between something like getDays() and getTotalDays(). And provide some usage examples, since some of it's not immediately apparent. It seems that sometimes a TimeSpan represents a difference in times, and sometimes it represents an absolute time. Clarification might be appropriate. As long as time can be a long, I'd modify the add(int, int) and subtract(int, int) methods to use longs as well. Also might be nice to check for overflow - though once you're using longs the incidence of that should be a lot rarer. (And I admit it will be pretty rare for ints as well.) And wouldn't be easier to maintain? Or for that matter, helper method like would simplify 3 other methods, and add some useful validation. Alternately the conversion factors could be put into a nice array, eliminating the switch entirely. Or, heck, the int values for DAYS, HOURS, etc. could be the conversion factors. Though that's probably a bit more confusing to others reading the code. Is there a reason to have getInstance(int, int) as a factory method, and also public constructors TimeSpan(long) and TimeSpan(Date)? Seems like the API would be cleaner if either they were all three constructors, or all three factory methods (with a single private constructor elsewhere). It's tempting to add units of WEEKS and YEARS, too. I admit YEARS is a bit of a problem though since the desired conversion factor is not obvious. (Which is why I don't mention MONTHS here.) Perhaps NONLEAP_YEARS (365 days), LEAP_YEARS (366), and STANDARD_YEARS (365.24...)? OK no one would have a good reason to make a TimeSpan of more than one consecutive leap year. :roll: But offering the option encourages people to decide what they really mean, which I think is good. [ January 28, 2003: Message edited by: Jim Yingst ]
Well, heck - might as well take advantage of the redefined units values to eliminate more redundant code: OK, not a big deal - I jut can't resist the need to remove redundancy. [ January 29, 2003: Message edited by: Jim Yingst ]
Good catch, Jim! By the way, you were right about using an IDE. I have the new NetBeans book from O'Rourke to review so I have been working with NetBeans to get an idea of how the thing works. Ok, so what is the easiest way to check for overflow or underflow? With the redesign there is only one place in the code where this can happen:
It seems to me that if both numbers are positive and the result is not positive then we had overflow and if both numbers are negative and the result is not negative we had underflow. Make sense? By the way, the GregorianCalendar class does not test for overflow. [ January 30, 2003: Message edited by: Thomas Paul ]
It seems to me that if both numbers are positive and the result is not positive then we had overflow and if both numbers are negative and the result is not negative we had underflow. Make sense? Yeah, good call - that seems sufficient to catch any overflow that might occur as the result of an addition. However the toMilliseconds() method could have overflow from multiplication too. And I don't believe this method will work as well for multiplication overflow, as an overflow result may be positive or negative. Here's code I came up with to check for overflow:
I went ahead and optimized the checks as much as possible - didn't see a way to create a single if statement in the add() method without some redundant checks. For the multiply version, I couldn't think of a better way than to just reverse the operation to see if it works. From limited testing it appears that these are significantly slower than traditional + or * due to method call overhead. You can improve performance substantially by manually inlining the method bodies into the calling code. Which means HotSpot doesn't do as good a job as I'd hoped at inlining for you. Ah well - for most applications the error checking is more useful than speed, I think. I think I may make a SafeMath class collecting utility methods like this. Perhaps I'll start a separate thread so y'all can review that too. By the way, the GregorianCalendar class does not test for overflow. Add this to the list of reasons not to like GregorianCalendar. Though at least this one is correctable without changing the API. And to be fair, once we're using longs the chance of overflow is pretty small for practical matters. I probably would've overlooked it in your class too if I hadn't noticed you were using ints in the first version; that's what got me thinking about it. [ February 09, 2003: Message edited by: Jim Yingst ]