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?
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.
nextWorkingDay
previousWorkingDay
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.
I am converting Gregorian dates to Islamic dates. I am setting its leap year pattern to Indian leap year but it is not working.
I make for loop and Gregorian date which takes current month and count is days and convert it to Islamic date. What i want
Here is my code
for(int i=0;i<maxDay;i++)
{
eng.add(String.valueOf(i+1));
DateTime dtISO=new DateTime(currentY,currentMonth+1,i+1,0,0);
DateTimeZone asia= DateTimeZone.forID("Asia/Riyadh");
DateTime dtIslamic = dtISO.withChronology(
IslamicChronology.getInstance(
asia,
IslamicChronology.LEAP_YEAR_INDIAN));
String islamicDateArr="";
split=dtIslamic.toString().split("T");
split=split[0].split("-");
if(i==0 || Integer.parseInt(split[2])==1)
{
isl.add(String.valueOf(split[2]+" "+islamicMonths[Integer.parseInt(split[1])-1]));
continue;
}
isl.add(String.valueOf(split[2]));
}
Your code seems to be correct.
Since you told me to have tried every of the four leap year patterns of Joda-Time without success I get the feeling there might be a bug or just a missing feature because among all supported leap year patterns there should be a pair of patterns which are different by one day (and you observe one day difference).
Other people have already submitted bug issues. See here:
issue 163
issue 107
As you can see it will be hard for you to convince the project leader to solve your problem for you. Maybe he is right when saying that Joda-Time has not a bug, but is just not complete.
Keep in mind that according to R.H. van Gent the calculated islamic calendar algorithm knows at least 8 instead of 4 variants because there are 4 intercalary schemes and (for each scheme) two variations depending on the precise start of the islamic epoch (Thursday versus Friday epoch). So Joda-Time is just not supporting all variants.
What are the alternatives to Joda-Time?
a) Java-8 and its backport Threeten-BP (for Java-6+7) support the table-driven Umalqura-calendar of Saudi-Arabia (sighting-based). I am not sure if this solves your problem however (if not then you might supply a hand-written file containing the table data relevant for you - a lot of work). Note that both libraries don't support algorithm-based islamic calendars.
b) Some people have written their own home-grown workarounds. I have found this hijri converter via Google. No idea if this works for you.
c) IBM offers a Hijri calendar in its ICU-project. It offers different leap year patterns than Joda-Time. Maybe it helps.
Side note: As you can see the current Java-support for Hijri calendars is not really satisfying. That is why I decided to set up a new implementation in my own library Time4J. It is scheduled for maybe 2-3 months later in autumn 2015.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Should I use Java date and time classes or go with a 3rd party library like Joda Time?
I could use some guidance about when it's worth using Joda Time rather than the basic java.util.Date class. What are the benefits? Does Joda Time let you do anything you can't do with the Date class, or is it just easier to work with or what?
Also, I've seen conflicting info about whether Joda Time is part of the standard API. Is it standard or not?
Java's standard date and time classes (mainly java.util.Date and java.util.Calendar) have limited functionality and have a number of design problems. The fact that many of the constructors and methods of java.util.Date are deprecated is one indication of this.
Joda Time has a much better thought out API than what's available in Java's standard library. There are classes for timestamps with or without a timezone, classes for holding only a date (year, month, day) or only a time of day, classes for periods, durations and intervals, it supports the ISO 8601 format (which is the standard format in XML documents) and much more.
I'd use Joda Time as my standard date and time library in any project - there really is no reason to use java.util.Date and java.util.Calendar.
Note that in a future release of Java, a new date and time API will most likely be included that's going to look a lot like what's currently available in Joda Time; see Project ThreeTen.
Also see Why Joda Time? on the home page of the Joda Time project.
Also, I've seen conflicting info about whether Joda Time is part of the standard API. Is it standard or not?
No, it isn't part of the standard API.
Update (copied from the comments):
Java 8 is out now, and it has a new date and time API which is similar to Joda Time (see the package java.time). If you're using Java 8, then please use the new date & time API.
I use the Joda time package to calculate durations between two historic instances in times in an Android application/activity. The two instances may for example have happened in the 19th century in Russia (Julian calendar system – before Russia adopted the Gregorian calendar system) and 20th Century western Europe (Gregorian calendar).
The inconvenience is that I now have to choose Julian or Gregorian chronologies based on my knowledge on specific countries actual cutover dates. These individual cutover dates can be found at Wikipedia or in the litterature.
As I see it, there are three solutions to my problems:
1) Look up all the cutover dates for the countries in literature. Then manually punch in the specific cutover date/time for the individual time zones. And use the factory setting in GJChronology.getInstance(zone, factorySettingCutoverDateTimeMillis, 4) where factorySettingCutoverDateTimeMillis is a long containing the milliseconds value of the specific instance in time when the cutover between Julian and Gregorian calendars happened in the specific DateTimeZone zone.
2) Identify where the specific cutover dates eventually are located in Jodatime (or elsewhere accessible in Android), and then make use of them.
3) Use the dafault GJChronology.getInstance(zone, null, 4) that specifies the default date in October 1582 (that is correct for many countries, but not all).
Solution 1) is possible, but require some manual labour to implement. Solution 2 is best, while solution 3) is where I am now using the default in the GJChronology or picking Julian or Gregorian if I know the particular calendar system used at that time.
I hope for help to arrive at solution 2) or get help to direct me to the best compiled cutover date/time list online to save work implementing solution 1). Thanks for your help.
I don't believe that Joda Time has that information within it - I certainly haven't come across it. The idea of a "country" doesn't really exist in Joda Time, and the cutover is not necessarily associated with a time zone either. That rules out solution 2, I believe.
I don't know of any official source of this information - I don't believe it's in the Unicode CLDR, for example... but could this page be useful to you? I have no idea of its reliabilty of completeness, but I guess it's a start :)
Every time I need to work with date and/or timstamps in Java I always feel like I'm doing something wrong and spend endless hours trying to find a better way of working with the APIs without having to code my own Date and Time utility classes. Here's a couple of annoying things I just ran into:
0-based months. I realize that best practice is to use Calendar.SEPTEMBER instead of 8, but it's annoying that 8 represents September and not August.
Getting a date without a timestamp. I always need the utility that Zeros out the timestamp portion of the date.
I know there's other issues I've had in the past, but can't recall. Feel free to add more in your responses.
So, my question is ... What third party APIs do you use to simplify Java's usage of Date and Time manipulation, if any? Any thoughts on using Joda? Anyone looked closer at JSR-310 Date and Time API?
java.time
Java 8 and later now includes the java.time framework. Inspired by Joda-Time, defined by JSR 310, extended by the ThreeTen-Extra project. See the Tutorial.
This framework supplants the old java.util.Date/.Calendar classes. Conversion methods let you convert back and forth to work with old code not yet updated for the java.time types.
The core classes are:
InstantA moment on the timeline, always in UTC.
ZoneIdA time zone. The subclass ZoneOffset includes a constant for UTC.
ZonedDateTime = Instant + ZoneIdRepresents a moment on the timeline adjusted into a specific time zone.
This framework solves the couple of problems you listed.
0-based months
Month numbers are 1-12 in java.time.
Even better, an Enum (Month) provides an object instance for each month of the year. So you need not depend on "magic" numbers in your code like 9 or 10.
if ( theMonth.equals ( Month.OCTOBER ) ) { …
Furthermore, that enum includes some handy utility methods such as getting a month’s localized name.
If not yet familiar with Java enums, read the Tutorial and study up. They are surprisingly handy and powerful.
A date without a time
The LocalDate class represents a date-only value, without time-of-day, without time zone.
LocalDate localDate = LocalDate.parse( "2015-01-02" );
Note that determining a date requires a time zone. A new day dawns earlier in Paris than in Montréal where it is still ‘yesterday’. The ZoneId class represents a time zone.
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
Similarly, there is a LocalTime class for a time-of-day not yet tied to a date or time zone.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
This post has a good discussion on comparing the Java Date/Time API vs JODA.
I personally just use Gregorian Calendar and SimpleDateFormat any time I need to manipulate dates/times in Java. I've never really had any problems in using the Java API and find it quite easy to use, so have not really looked into any alternatives.
The Apache Commons Lang project has a DateUtils class that performs helpful Date operations.
I use DateUtils.truncate() a lot, which will "zero out" parts of the Date for you (helpful if you want your Date object to, say, represent a date and not include any time information). Each method works for both Date and Calendar objects too.
http://commons.apache.org/lang/
I've been using Joda exclusively for three years now and would definitely recommend it - it has the whole area covered with an interface that 'does what it says'.
Joda can look complex when you start, as eg it has concepts of periods, duration and intervals which look sort of similar, but you can start off simply by substituting org.joda.time.DateTime (or org.joda.time.DateMidnight) for java.util.Date in your code, and sticking with the many useful methods that those classes contain, before understanding the other areas.
Im using GregorianCalendar - always and everywhere. Simple java.util.Date is too complex, yeah.
So, my advice is - use GC, its simple
It's the same in javascript. Someone must have been smoking something when they think it's a good idea to let 2008 mean the year 2008, 31 to mean the 31st day in the month, and - this is the best part - 11 to mean the 12th month.
On the other hand, they got it right on two out of three.
The thing that always gets me with Java is the date time library. I've never used Joda, just briefly look at it, looks like its a pretty good implementation, and if I understand JSR-130 correctly its taking knowledge from Joda and eventually having it included in JavaSE.
Quite often for past projects I've wrapped the Java date time objects, which in itself was quite a task. Then used the wrappers for date manipulation.
Date APIs are very difficult to design, especially if they have to deal with localization. Try to roll your own and see, it's worth doing at least once. The fact that Joda was able to do such a good job is a real credit to its developers. To answer your question, I've heard nothing but good things about that library, though I have never played around with it myself.
A lot of programmers begin by using Date, which has numerous deprecated overloaded constructors (making it difficult to use), but once you figure out GregorianCalendar it becomes a little bit easier to manage. The example here is pretty helpful:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/GregorianCalendar.html
It's really simple to write your own date API which sits on top of the raw Java classes, Date and Calendar. Basically both date and Calendar suffer from the fact that they are trying to cram two concepts into one class:
Date (i.e. Year-Month-Day)
Instant (i.e. currentTimeMillis)
When you understand this, it will just revolutionize how you handle date-like concepts in your code. Things will be simpler, clearer, better. In every sense!
For me, Joda is over-complicated, at least for the overwhelming majority of purposes and I particularly don't like the fact that they have gone against standard Java forms, one example being how they parse and format dates. Stephen Colebourne, the guy behind JODA, is the spec lead of JSR-310 and this suffers from the same problems imho (I've followed and contributed to the discussions for the last few years).
Do it yourself; it's easy. Just fill in the following classes: MyDate (wrapping year-month-day), Month (an enum), TimeOfDay (hour-min-sec-millis), DayOfWeek (enum), Instant (wrapping a long). Always consider time-zones when converting between Instants and Dates.
If this seems daunting, you can use Calendar and SimpleDateFormat under the hood. You'll do this in a day and never regret it.