2

I need to implement a labor calendar able to count working days and, of course, natural days. The calendar must be able to handle national holidays and these days must be submitted by the user. So, if I need to calculate the difference between two days the counting must ignore Saturdays, Sundays, and Holidays.

The Java class Calendar, doesn't handle holidays or working days, so I need to make it by myself. I have think two possible ways:

First way:

I could implement a new Day class which would have a boolean isHoliday to check if that is a working day or not, then create a new class with all the methods I'd need to handle/count the days.

Pros:

  • Easy to handle
  • I can override/create methods like toString, toDate, etc...

Cons:

  • Heavy (Maybe?)

My doubt about this approach is how to store it. It'd mean to make 365 objects and store them in a Listor Linked List and that's a lot of data to handle.

Second way:

My second idea is to make it more simple. Create an array of Strings or Dates where I'd store the holidays. Example new ArrayList<String> freeDays = ["01/01/2019", "05/01/2019", "06/01/2019"...] and with work with it using a new CalendarUtils class or something like that.

Pros:

  • More readable
  • Light

Cons:

  • Hard to work with

For me the first option looks better, however, I don't want to waste memory or use bad practices.

Which option looks better? Are there any third option?

Community
  • 1
  • 1
  • There's a few other questions with ideas, e.g. these two and the others they link to: https://stackoverflow.com/questions/24114155/how-to-get-current-date-and-add-five-working-days-in-java https://stackoverflow.com/questions/10854119/calculate-business-days-including-holidays – Rup Aug 01 '18 at 16:15

1 Answers1

5

Avoid legacy date-time classes

Never use Date or Calendar classes. Those terribly troublesome old classes are now legacy, supplanted by the java.time classes, specifically Instant and ZonedDateTime. You may find LocalDate helpful too.

Smart objects, not dumb strings

Never use strings to represent date-time within your Java code. Use objects, the java.time classes.

When exchanging date-time values as text, always use the standard ISO 8601 formats. The java.time classes use these formats by default when parsing/generating strings. For a date that would be YYYY-MM-DD such as 2018-01-23.

TemporalAdjuster interface

To skip weekends, use the TemporalAdjuster implementation found in the ThreeTen-Extra project.

Example:

LocalDate                        // Represent a date-only value, without a time-of-day and without a time zone. 
.now(                            // Capture the current date. 
    ZoneId.of( "Africa/Tunis" )  // Time zone required. For any given moment the date varies around the globe by zone. 
)
.with(                           // Invoke a `TemporalAdjuster` implementation. 
    org.threeten.extra.Temporals.nextWorkingDay() 
)                                // Returns a `LocalDate`. Using immutable objects pattern, producing a fresh object based on the values of another while leaving the original unaltered. 

To skip holidays, you must write your own code. No two people, companies, or countries share the same definition of holidays.

You’ll need to define your own list of holidays. I suggest writing that as an implementation of TemporalAdjuster for working neatly with the java.time classes. Perhaps nextBusinessDay and previousBusinessDay. That ThreeTen-Extra project mentioned above is open-source, so look to there for code to guide you. And I vaguely recall posting one or more implementations of TemporalAdjuster myself here on Stack Overflow.

You might store those holiday dates in a database for persistence. And represent them at runtime in chronological order as a List< LocalDate >, sorted with Collections.sort and searching with Collections.binarySearch. But beware of thread-safety. You’ll likely need to update that list during runtime. Writing while reading must be protected. Search for more info. And read the excellent book, Java Concurrency in Practice by Brian Goetz et al.

You can combine your holiday-skipping code with weekend-skipping code. Use a search engine to find my Answers on weekend-skipping using EnumSet and DayOfWeek enum. (The search feature built into Stack Overflow unfortunately skews towards Questions while ignoring Answers.)

Search Stack Overflow. All of this has been asked and answered before.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154