Don’t use java built-in classes, use jodatime and enforce this rule with sonar !
Don’t use java built-in classes
How many bugs in 5 lines of code ?
Date date = new Date(2007, 12, 13, 16, 40); TimeZone zone = TimeZone.getInstance("Europe/Bruxelles"); Calendar cal = new GregorianCalendar(date, zone); DateFormat fm = new SimpleDateFormat("HH:mm Z"); String str = fm.format(cal);
Just 6 bugs !
int year = 2007 - 1900; int month = 12 - 1; Date date = new Date(year, month, 13, 16, 40); TimeZone zone = TimeZone.getInstance("Europe/Brussels"); Calendar cal = new GregorianCalendar(zone); cal.setTime(date); DateFormat fm = new SimpleDateFormat("HH:mm Z"); fm.setTimeZone(zone); Date calDate = cal.getTime(); String str = fm.format(calDate);
If you want deeper explanations see this [presentation]
java.util.Date issues
- From JDK1.0
- Uses two digit years (from 1900)
- January is 0, December is 11
- Should have been immutable
- Most methods deprecated in JDK1.1
- Uses milliseconds from 1970 representation
java.util.Calendar issues
- From JDK1.1
- Uses subclasses for different calendar systems
- January is 0, December is 11
- Should have been immutable
- Uses dual representation internally
- value for each field
- milliseconds from 1970 representation
- Odd performance and bugs
java.util.DateFormat issues
- Pattern based date formatting
- “dd MMM yyyy”
- Requires Date object
- Not thread-safe : see rule findbugs : Multithreaded correctness – Call to static DateFormat
- Not especially fast
- Sun RFE to make thread-safe ignored
SQL – java.util.sql.Date, Time, Timestamp issues
Subclass java.util.Date
- Date extends Date (!)
- Time extends Date (!)
- Override superclass to block methods (throws Exception)
- Timestamp adds nanoseconds
- equals() broken
- All the problems of java.util.Date and more
- timezone problem new Time(long)
Avoid millis manipulation and let’s use Jodatime !
when playing with java.util.Date you end up doing calculation in millis
int
days =
40
;
Date now =
new
Date();
long
nowMillis = now.getTime();
Timestamp nowTimestamp =
new
Timestamp(nowMillis);
long
future =
3600
*
24
* days *
1000
;
Timestamp expiryTimestamp =
new
Timestamp(nowMillis + future);
System.out.println(
"nowTimestamp "
+ nowTimestamp);
System.out.println(
"expiryTimestamp "
+ expiryTimestamp);
this last code sample contains a bug… int vs long for days !
see this explaination the expiryTimestamp is before the nowTimestamp for “large days count”
nowTimestamp 2011-02-04 12:45:40.381
expiryTimestamp 2011-01-25 19:42:53.085
now let’s write the same code with joda time
DateTime nowTimestamp2 =
new
DateTime();
System.out.println(
"nowTimestamp "
+ nowTimestamp2);
System.out.println(
"expiryTimestamp "
+ nowTimestamp2.plusDays(days));
it’s more readable… and most important it return the correct value 😉
nowTimestamp 2011-02-04T12:45:40.443+01:00
expiryTimestamp 2011-03-16T12:45:40.443+01:00
Sonar to the rescue
sonar can detect these issues :
- Multithreaded correctness – Call to static Calendar
- Multithreaded correctness – Call to static DateFormat
to fix them with jodatime let’s use the DateTimeFormat.
fmt
=DateTimeFormat.forPattern("MMMM, yyyy");DateTime datetime = fmt.parseDateTime(duedate);
this one is threadsafe and can be static and final field. or use the toString
datetime.toString("dd:MM:yy");
but the step further is to banish jdk date from your code base !
To do so, let’s define sonar architectural constraint like
- Arch : avoid java.util.GregorianCalendar
- Arch : avoid java.util.Date
- Arch : avoid java.text.SimpleDateFormat
- Arch : avoid java.sql.Timestamp
- Arch : avoid java.sql.Date
to banish jdk dates from your model, you may implement hibernate usertype, jaxb adapter,…
#1 by prabhakaran on April 14, 2012 - 11:45 am
Great work dude. The presentation is not found in your web page.
#2 by mestachs on April 14, 2012 - 3:28 pm
thanks, I hope this will work better. http://www.parleys.com/#st=5&id=100&sl=2
#3 by mestachs on February 15, 2016 - 9:47 am
more time related discussions
* http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time
* https://www.washingtonpost.com/news/worldviews/wp/2016/02/12/the-radical-plan-to-destroy-time-zones-2/
* https://news.ycombinator.com/item?id=11101863
#4 by Phil on October 12, 2017 - 2:25 pm
Has anyone benchmarked the difference in performance between using the EqualsBuilder and writing equals with short-cut operators? Is the EqualsBuilder’s code simple enough for inlining and would this actually result in short-cuts being generated? I know, I know… I could go try it for myself. I’m being lazy. But still, is it worth thinking about? Equals and comparisons (both of which have builders) are pretty fundamental to a lot of programs and are often used in loops of various forms.
#5 by mestachs on May 29, 2018 - 5:34 pm
Another great piece on how time is hard to deal with : https://zachholman.com/talk/utc-is-enough-for-everyone-right