A good library of business calendars in Java?

Does anyone know a good business calendar in java?

He should handle frivolous date calculations, taking into account the holidays.

Ideally, in addition to setting the holidays and days of the company, we should also be able to set the working hours on a daily basis so that we can calculate SLA and KPI for working hours.

I know that something like this is part of jboss jBpm, but I was wondering if it was some other project doing this.

Of course, open source is a big plus!

+33
java open-source calendar
Jun 25 '09 at 16:34
source share
8 answers

Check out this library, it has functionality for the holidays, etc., it is built around joda.

http://objectlabkit.sourceforge.net/

+18
Feb 26 '10 at 10:03
source share

Below is a very long answer. This is what I put together for this purpose. It is not super convenient, but it should give you what you are looking for.

It builds on the Apache community project, available here: http://commons.apache.org/lang/

package com.yourPackageName; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.time.DateUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class BusinessDayUtil { private static Log log = LogFactory.getLog(BusinessDayUtil.class); private static transient Map<Integer, List<Date>> computedDates = new HashMap<Integer, List<Date>>(); /* * This method will calculate the next business day * after the one input. This means that if the next * day falls on a weekend or one of the following * holidays then it will try the next day. * * Holidays Accounted For: * New Year Day * Martin Luther King Jr. Day * President Day * Memorial Day * Independence Day * Labor Day * Columbus Day * Veterans Day * Thanksgiving Day * Christmas Day * */ public static boolean isBusinessDay(Date dateToCheck) { //Setup the calendar to have the start date truncated Calendar baseCal = Calendar.getInstance(); baseCal.setTime(DateUtils.truncate(dateToCheck, Calendar.DATE)); List<Date> offlimitDates; //Grab the list of dates for the year. These SHOULD NOT be modified. synchronized (computedDates) { int year = baseCal.get(Calendar.YEAR); //If the map doesn't already have the dates computed, create them. if (!computedDates.containsKey(year)) computedDates.put(year, getOfflimitDates(year)); offlimitDates = computedDates.get(year); } //Determine if the date is on a weekend. int dayOfWeek = baseCal.get(Calendar.DAY_OF_WEEK); boolean onWeekend = dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY; //If it on a holiday, increment and test again //If it on a weekend, increment necessary amount and test again if (offlimitDates.contains(baseCal.getTime()) || onWeekend) return false; else return true; } /** * * This method will calculate the next business day * after the one input. This leverages the isBusinessDay * heavily, so look at that documentation for further information. * * @param startDate the Date of which you need the next business day. * @return The next business day. IE it doesn't fall on a weekend, * a holiday or the official observance of that holiday if it fell * on a weekend. * */ public static Date getNextBusinessDay(Date startDate) { //Increment the Date object by a Day and clear out hour/min/sec information Date nextDay = DateUtils.truncate(addDays(startDate, 1), Calendar.DATE); //If tomorrow is a valid business day, return it if (isBusinessDay(nextDay)) return nextDay; //Else we recursively call our function until we find one. else return getNextBusinessDay(nextDay); } /* * Based on a year, this will compute the actual dates of * * Holidays Accounted For: * New Year Day * Martin Luther King Jr. Day * President Day * Memorial Day * Independence Day * Labor Day * Columbus Day * Veterans Day * Thanksgiving Day * Christmas Day * */ private static List<Date> getOfflimitDates(int year) { List<Date> offlimitDates = new ArrayList<Date>(); Calendar baseCalendar = GregorianCalendar.getInstance(); baseCalendar.clear(); //Add in the static dates for the year. //New years day baseCalendar.set(year, Calendar.JANUARY, 1); offlimitDates.add(offsetForWeekend(baseCalendar)); //Independence Day baseCalendar.set(year, Calendar.JULY, 4); offlimitDates.add(offsetForWeekend(baseCalendar)); //Vetrans Day baseCalendar.set(year, Calendar.NOVEMBER, 11); offlimitDates.add(offsetForWeekend(baseCalendar)); //Christmas baseCalendar.set(year, Calendar.DECEMBER, 25); offlimitDates.add(offsetForWeekend(baseCalendar)); //Now deal with floating holidays. //Martin Luther King Day offlimitDates.add(calculateFloatingHoliday(3, Calendar.MONDAY, year, Calendar.JANUARY)); //Presidents Day offlimitDates.add(calculateFloatingHoliday(3, Calendar.MONDAY, year, Calendar.FEBRUARY)); //Memorial Day offlimitDates.add(calculateFloatingHoliday(0, Calendar.MONDAY, year, Calendar.MAY)); //Labor Day offlimitDates.add(calculateFloatingHoliday(1, Calendar.MONDAY, year, Calendar.SEPTEMBER)); //Columbus Day offlimitDates.add(calculateFloatingHoliday(2, Calendar.MONDAY, year, Calendar.OCTOBER)); //Thanksgiving Day and Thanksgiving Friday Date thanksgiving = calculateFloatingHoliday(4, Calendar.THURSDAY, year, Calendar.NOVEMBER); offlimitDates.add(thanksgiving); offlimitDates.add(addDays(thanksgiving, 1)); return offlimitDates; } /** * This method will take in the various parameters and return a Date objet * that represents that value. * * Ex. To get Martin Luther Kings BDay, which is the 3rd Monday of January, * the method call woudl be: * * calculateFloatingHoliday(3, Calendar.MONDAY, year, Calendar.JANUARY); * * Reference material can be found at: * http://michaelthompson.org/technikos/holidays.php#MemorialDay * * @param nth 0 for Last, 1 for 1st, 2 for 2nd, etc. * @param dayOfWeek Use Calendar.MODAY, Calendar.TUESDAY, etc. * @param year * @param month Use Calendar.JANUARY, etc. * @return */ private static Date calculateFloatingHoliday(int nth, int dayOfWeek, int year, int month) { Calendar baseCal = Calendar.getInstance(); baseCal.clear(); //Determine what the very earliest day this could occur. //If the value was 0 for the nth parameter, incriment to the following //month so that it can be subtracted alter. baseCal.set(year, month + ((nth <= 0) ? 1 : 0), 1); Date baseDate = baseCal.getTime(); //Figure out which day of the week that this "earliest" could occur on //and then determine what the offset is for our day that we actually need. int baseDayOfWeek = baseCal.get(Calendar.DAY_OF_WEEK); int fwd = dayOfWeek - baseDayOfWeek; //Based on the offset and the nth parameter, we are able to determine the offset of days and then //adjust our base date. return addDays(baseDate, (fwd + (nth - (fwd >= 0 ? 1 : 0)) * 7)); } /* * If the given date falls on a weekend, the * method will adjust to the closest weekday. * IE If the date is on a Saturday, then the Friday * will be returned, if it a Sunday, then Monday * is returned. */ private static Date offsetForWeekend(Calendar baseCal) { Date returnDate = baseCal.getTime(); if (baseCal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) { if (log.isDebugEnabled()) log.debug("Offsetting the Saturday by -1: " + returnDate); return addDays(returnDate, -1); } else if (baseCal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { if (log.isDebugEnabled()) log.debug("Offsetting the Sunday by +1: " + returnDate); return addDays(returnDate, 1); } else return returnDate; } /** * Private method simply adds * @param dateToAdd * @param numberOfDay * @return */ private static Date addDays(Date dateToAdd, int numberOfDay) { if (dateToAdd == null) throw new IllegalArgumentException("Date can't be null!"); Calendar tempCal = Calendar.getInstance(); tempCal.setTime(dateToAdd); tempCal.add(Calendar.DATE, numberOfDay); return tempCal.getTime(); } } 
+5
Jun 26 '09 at 4:52
source share

There is an API that calculates a list of holidays depending on the country / region. See jollyday.sourceforge.net . You can combine this with ObjectLabKit or the aforementioned calculation logic or whatever you like. Jollyday allows you to have your own set of holidays configured in an XML file.

+4
Nov 08 '10 at 20:20
source share

to calculate the date try joda-time.sourceforge.net

but I have no idea what you mean by setting up the holidays. because each country has different holidays. but try this first, it’s good for calculating date and time.

+3
Jun 25 '09 at 16:38
source share

jBPM (at least v3) has a good business calendar .

If you don’t need all the dependency on JBPM, I think you can take out only the calendar package

+3
Feb 08 '10 at 11:52
source share

I would suggest creating your own home holiday class, which you can manage each of the holidays. All holidays have rules on what day they will be. It is easy to program these dates every year.

Martin Luther King, for example:

 private static Date holidayHumanRights(int parmYear) { Date tempDate = new Date(parmYear, 0, 1); //January 1st... try { tempDate = getNextDayofWeek(tempDate, "Monday"); //now point towards the 3rd Monday, which would be 2 weeks from //current Monday date... tempDate.advanceDays(2*7); } catch (Exception ex) { //throw or suppress the error, your choice System.err.println(ex.toString()); } return tempDate; } 
0
Jun 25 '09 at 16:49
source share

Thinking of the same problem, I discovered the Quartz calendar . This has several issues, such as:

  • This is part of the implementation of the planning library - using it separately from the entire quartz, as the holiday calendar is a bit hacky.
  • It has a getNextIncludeTime method, but not getPrevIncludeTime .
  • It has an ugly and inconsistent API - AnnualCalendar has a getter and setter that accepts an ArrayList, MonthlyCalendar has a getter and setter that accepts boolean [], both of which simply expose the internal elements of the class.
  • It has some poorly documented problems - you can bind calendars, but the order of the chain is important - the DailyCalendar created on the AnnualCalendar is fine, the AnnualCalendar created on the DailyCalendar will break (hang, I think).

However, this is the best I could find. So maybe just grab the source code, fix what's wrong, and add the missing?

0
Feb 08 '10 at
source share

I recently developed this open source project http://lamma.io , which is designed to create a date.

For example:

 Date(2015, 10, 5) to Date(2015, 10, 15) by 2 except Weekends 

will give

 List(2015-10-05, 2015-10-07, 2015-10-09, 2015-10-13, 2015-10-15) 

The project is licensed in accordance with DO WHAT YOU WANT A PUBLIC LICENSE, so feel free to use / redistribute :)

0
Jun 09 '14 at 20:33
source share



All Articles