About Java and JRuby Development
JEE, Spring, Guice
Hibernate, Java Persistence (JPA)
and various Web Frameworks

Hot topics

eBook shop

PDF edition of articles

Window id concept

An approach to leverage the use of the HTTP session

Web Framework Test and Analysis

Article series on web technologies with detailed reviews.

Hibernate eBook

A continuously updated book on Hibernate and Java Persistence

Friendly Java Date API, calculate with dates, working day calculation

I wrote a hopefully friendly API on top of the java.util.Date and java.util.Calendar classes. The intention is to be able to do a number of things more easily

Edition

February 2009 by Sebastian Hennebrueder

Library versions

Download

PDF of this tutorial

http://www.laliluna.de/download/friendly-java-date-api.pdf

Source code

http://www.laliluna.de/download/friendly-java-date-api.zip

Charges and License

The Friendly Date API is published under the Open Source Robin Hood License. The license details can be found here.

http://www.laliluna.de/open-source-robin-hood-license.html

It requires a licence if you use it inside of a company or organization, which exceeds a turnover or budget of 2 Million Euros.

Using the Friendly API

The Date class is the central element. It is a mutable class which encapsulates access to a java.util.Calendar.

There are two useful enums Days and Months providing access to human readable presentations of day and month.

The corresponding Integer values of Monday is 1, Tuesday 2, ... Sunday is 7.

The corresponding Integer values of the months are 1 for January, 2 for February, 12 for December.

Creating dates

// the current date and time
date = new Date();
date = Date.now();

// the current date and time set to 00:00:00
date = Date.today();

// defining a timezone different to the one of your computer
date = new Date(TimeZone.EUROPE_BELFAST);
date = Date.now(TimeZone.EUROPE_BELFAST);

// creating explicitly 2009, February 12th
date = new Date(2009, 2, 12);
// 15:30 on 2009, Feb 12 th
date = new Date(2009, 2, 12, 15, 30);

// creating (cloning) from another date
Date other = new Date();
date = new Date(other);
date = new Date(GregorianCalendar.getInstance());
date = new Date(new java.util.Date());

Comparing dates

The API allows to compare for date and time (default), only date or only time. There are methods which follow the behavior of the Comparable interface but you may use the before / after / equal methods for a better human readable impression.

    Date date = Date.now().setHour(14);
Date later = Date.now().addHours(2);
// true
date.equalDate(later);
// false
date.equalDateTime(later);
// false
date.equalTime(later);

// true
date.before(later);
// false
date.after(later);

// false, we have the same date
date.beforeDate(later);
// true, the time is earlier
date.beforeTime(later);

Changing a date or time zone

    Date date = Date.now();

// You can add or set values for year, month, day,
// hour, minute, second, millisecond
date.addHours(5);
date.addMonths(2);
date.setMinute(30);

// Just change the time zone
date.setTimeZone(TimeZone.AMERICA_NEW_YORK);
// Translate the current time to a different time zone
date.translate(TimeZone.AFRICA_BAMAKO);

Calculating with dates and fractions

A very nice concept is taking from Ruby. Ruby has native support for fractions. You might remember them from school.

50 % =  1/2
one third is 1/3

Fractions are calculated from a day perspective. Fractions are not mutable.

1/1 = a day
1/24 = an hour
25/24 = a day and an hour
2/1440 = 2 minutes

Here is the Java code

// 5 hours and 30 minutes
new Fraction(5, 24).plus(30, 60 * 24);

// 2 days, 3 hours and 20 minutes
new Fraction(2,1).plus(3, 24).plus(20, 60*24);

The date class has a couple of ready made fractions like

// an hour
Fraction anHour = Date.HOUR;
// a minute
Fraction aMinute = Date.MINUTE;
// a second
Fraction aSecond = Date.SECOND;

// five hours
Date.HOUR.times(5);
// 20 minutes
Date.MINUTE.times(20);
// 5 seconds
Date.SECOND.times(5);



Fractions can be used to add or remove time from a date.

/* Add 5.5 hours to the current date and time */
Fraction _55 = Date.HOUR.times(5).plus(Date.MINUTE.times(30));
Date.now().add(_55);

// substract 600 minutes from the current date
Date.now().substract(Date.MINUTE.times(600));



A fraction is the result of a subtraction from two dates as well.

// calculatge the difference between two dates
Date now = Date.now();
Date later = new Date(now).addDays(5);
Fraction delta = later.minus(now);
// the difference is 5 days, so the following is true
delta.equals(new Fraction(5,1));

Calculating working days

Working days are normally Monday to Friday. The basic methods doesn't know about holidays and don't want to know it.

In Germany every Bundesland (same as state in other countries) has its own special holidays and even some cities have a special holiday. I don't want to implement this for the whole world.

As a consequence you can define a DayFilter which can filter the working days by your special holiday filter.

Date now = Date.now();
Date later = new Date(now).addDays(5);
from.workingDaysBetween(to)

Date now = Date.now();
Date later = new Date(now).addDays(5);
now.workingDaysBetween(later);

// working days with a day filter
DayFilter filter = new MyBadVilbelGermanyHolidayFilter();
now.workingDaysBetween(later, filter);

Printing dates

Printing is very limited. Basically you can only extract the values from the date class and get the month and day names in a short and a long version.

But you can always fall back to Java formatting.

Date date = Date.today();
// time
String.format("%02d:%02d:%02d", date.hour(), date.minute(), date.second());
// time in english format
String.format("English: %02d:%02d:%02d %s", date.hour12(), date.minute(), date.second(),date.am() ? "AM" : "PM");
// printing English names for day and month
String.format("%s %s, %d %d", date.dayShort(), date.monthName(), date.day(), date.year());

// fall back to Java formatting
SimpleDateFormat dateFormat = new SimpleDateFormat();
dateFormat.format(Date.today().toJavaDate());



I hope you enjoy the API.



Best Regards / Viele Grüße



Sebastian Hennebrueder