Best way to handle Java Calendar with working days? - java

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.

Related

Pattern.format(date) vs Date.fomat(Pattern)?

I came to know that DateTimeFormatter has two implementation for formatting the date.
Pattern.format(date)
Date.format(pattern)
public static void main(String[] args) {
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("MM/dd/yyyy");
LocalDate date = LocalDate.now();
String dateFormatText = date.format(pattern);
String patternFormatText = pattern.format(date);
System.out.println(dateFormatText);
System.out.println(patternFormatText);
}
Both the SysOut prints the same value.
The Oracle docs examples uses Date.format method, whereas I can see many tech blogs using the Pattern.format method.
Can anyone explain me what is the difference and which is best to use?
Source Code Demo : Here
Though opinion-based I will try an answer.
As Stephen C has already documented, the two forms are equivalent.
Which is best? As so often in programming the answer is: It‘s best to write what will be least surprising to those reading your code.
So what will be least surprising? I am sure that the answer varies. Your organization will — consciously or unconsciously — build a tradition for what you are doing, and the least surprising will be to follow that tradition.
Points of each option
I’d also like to take a look at some thinkable reasons why both options have crept into java.time. This may give us some further thoughts on advantages of one or the other.
And since I don’t do mind reading, it’s guesswork. I think that the form date.format(formatter) was formed with inspiration from at least two sides:
It’s parallel to date.toString(), which with java.time we also often use for formatting a date-time object to a string. In Joda-Time, the predecessor of java.time, we even had the same method name: date.toString(formatter).
It’s somehow parallel to DateType.parse(string, formatter), which is what we use for the opposite operation, converting the string to a date-time object. For example LocalDate.parse("08/04/2021", pattern). This form in turn is necessary with the design of java.time. formatter.parse(string) wouldn’t know whether to parse into a LocalDate, an Instant, a ZonedDateTime or one of the many other date-time types of java.time. (The form pattern.parse("08/04/2021", LocalDate::from) exists as an alternative, though, and is sometimes necessary, but not often used.)
And I may be missing something, but one reason why many tech blogs use formatter.format(date) is inspiration from the now obsolete SimpleDateFormat that consistently used format.format(date). I cannot completely escape the thought that maybe those bloggers have not fully gone into the java.time way of thinking.
Can anyone explain me what is the difference?
There is no significant difference.
The javadoc for LocalDateTime.format says:
public String format(DateTimeFormatter formatter)
Formats this date-time using the specified formatter.
This date-time will be passed to the formatter to produce a string.
In other words, LocalDateTime.format calls DateTimeFormatter.format.
... and which is best to use?
Neither is "best".
It is up to you decide which form expresses your intention more clearly. Do you want to say:
"LocalDateTime: format yourself with this formatter", or
"DateTimeFormatter: format this temporal value".

Java Best Practice for Date Manipulation/Storage for Geographically Diverse Users

I have read all of the other Q/A about Date Manipulation, but none of them seems to deliver a satisfactory answer to my concern.
I have a project with geographically diverse users which uses Date in some of its classes and data. The thing is that I am looking for an efficient way to manipulate the Dates for the different users in their respective timezone, most of the answers suggest using Joda library for Date manipulation, which quite don't understand yet because I still have not found any operation you cannot do with traditional Java, so if someone can explain what can I do with Joda that can't be done with traditional Java, then I may consider using it.
I finally came to the approach of using System.currentTimeMillis() to save my dates into the database (any database). This would avoid me to worry about what timezone is using the database to store the dates. If I want to query the database for an specific date or range of dates, I would perform the queries using the long value of the Date I want to query:
SELECT * FROM table1 WHERE date1>=1476653369000
And when retrieving a ResultSet I would then format the long value retrieved from database to a readable Date using the timezone of the user requesting the data.
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(resultSet.getLong(1));
cal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
Date myDate = cal.getTime();
According to some opinions I have read, some people say emphatically that storing System.currentTimeMillis() is definitely not the best practice, nevertheless, for some reason they all miss to say WHY it is not recommendable. Am I missing something? Does this cause a performance issue for the conversions Long->Date/Date->Long? Is there any use case that cannot be accomplished when using Long instead Date in database? Can someone post a rationale explanation about this?
In the other hand, assuming that I keep using Date values to store dates in database, is there a way to avoid worrying about time-zones while handling database Date?
Thanks in advance.
I have read all of the other Q/A about Date Manipulation
No, you certainly did not read them all.
You would have learned that both the legacy date-time classes (such as java.util.Date & java.util.Calendar) and the Joda-Time project are supplanted by the java.time classes (1,890 results for search on 'java.time').
You would have learned not to track date-time values as a count-from-epoch. Debugging and logging becomes very difficult with bugs going undiscovered as humans cannot decipher the meaning of a long integer as a date-time. And because many granularities of counting (whole seconds, milliseconds, microseconds, nanoseconds, whole days, and more) and at least a couple dozen of epochs are employed in various software projects create ambiguity about your data with assumptions leading to errors, misinterpretation, and confusion.
You would have learned to use date-time types in your database to track date-time values.
You would have learned to work and store date-time values in UTC. Adjust into a time zone only where required by logic or as expected by the user for presentation. “Think global, present local.”
You would have learned that while a valiant industry-first effort, the legacy date-time classes are poorly designed, confusing, and troublesome. See What's wrong with Java Date & Time API? for some discussion. Joda-Time was the first good date-time library in the industry, and inspired its replacement, the java.time classes built into Java 8 and later.
I'll be somewhat brief as all of this has been covered many times already on Stack Overflow.
Work in UTC. In Java that means the Instant class is commonly used. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now();
Any serious database such as Postgres tracks date-time values in UTC. Your JDBC driver handles the detail of converting from database internally-stored data to a Java type. JDBC drivers that comply with JDBC 4.2 and later can directly handle java.time types via PreparedStatement::setObject & ResultSet::getObject methods.
myPreparedStatement.setObject( … , instant );
For non-compliant drivers, fall back to using java.sql types such as java.sql.Timestamp to communicate with database, and convert to/from java.time types via new methods added to the old classes. The internal details of how the database handles date-time values may be quite different than how java.time does. For the most part the JDBC driver hides all the nitty-gritty details from you. But one critical issue is resolution, which you should study in your database. The java.time classes handle date-times with a resolution up to nanoseconds but your database may not. For example, Postgres uses a resolution of microseconds. So going back-and-forth means data-loss. You want to use the truncation methods on the java.time classes to match your database.
myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) );
So, no time zone involved. So no “worrying about time-zones while handling database Date”.
When you want to see the same moment through the lens of a region’s wall-clock time, apply a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );
When taking a zoned date-time back to the database, extract an Instant.
Instant instant = zdt.toInstant();
Be aware that for any given moment, the date as well as the time-of-day varies around the globe by time zone. So if an exact moment matters, such as when a contract expires, beware of using a date-only value. Either use a date-time value for the exact moment, or store the intended time zone alongside the date-only so the exact moment can be calculated later.
LocalDate ld = LocalDate.of( 2016, 1 , 1 );
// Determine the first moment of 2016-01-01 as it happens in Kolkata.
ZonedDateTime zdt = ld.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) );
Instant instant = zdt.toInstant(); // Adjust to UTC and store.
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, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
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 and 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 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….
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.
what can I do with Joda that can't be done with traditional Java
It's not really about what you can or cannot do with traditional Java in the general case. It's more about how the library API works to make you write better (more robust and correct) code easier than traditional Java does.
So much so that as of Java 8 the Joda API was more or less copied/adopted verbatim with just package names changed and incorporated into the Java 8 SE standard library.
Therefore if you are using Java 8 you should pick the new API, and if not you should consider that using Joda will at least buy you a smooth path towards upgrading/porting to Java 8 when you are able to.
A few examples:
Consistent API for date and time types.
Date/time objects are immutable, manipulations return new instances of the type representing the altered value. (Like Java Strings). This makes it easier to reason about reuse of date/time objects.
By design avoids mixing DST & timezone dependent values/operations with DST & timezone agnostic ones. This makes it a lot easier to write code that works consistently and correctly and doesn't have corner cases dependent on timezone/locale/date/time-of-day.
Sane defaults for things like toString() so serialising/deserialising can be expected to work correctly with minimal effort.
Culture/locale dependent corner cases and things you weren't aware of yet (for example, did you know about the traditional Korean calendar?) which saves you a whole lot of hassle when converting your date times between locales/calendaring systems. Also: a wealth of formatting options.
The concept of Instants to represent 'absolute' time stamps which is useful when working with geographically distributed systems (when the system default clocks/timezones & DST rules may differ) or for interop because it uses UTC.
EDIT to add:
According to some opinions I have read, some people say emphatically that storing System.currentTimeMillis() is definitely not the best practice, nevertheless, for some reason they all miss to say WHY it is not recommendable. Am I missing something?
System.currentTimeMillis() has a few downsides. The big drawback is that the type of clock is ill defined. It could be a monotonic clock, it could be clock subject to DST and timezone or it could be a UTC time. It is also not necessarily an accurate clock, it is not actually guaranteed to be accurate down to the millisecond. Just whatever happens to be to hand for something that will work as a semblance of the current time at the current time, basically.
This means that if you want to use multiple servers to handle incoming requests, for instance, it gets tricky when you have to consider working with the output of System.currentTimeMillis() from server A in the context of your program running on a different server B the next day, say.

BC dates, LocalDate and DatePicker

I am currently working on a simple program to create and display timelines for history students and I ran into a problem.
When creating a new event, users have to fill a little form including DatePickers object to select start date and end date for the event. My problem is with date Before Christ or negative date. I can't seem to use them. Hence my questions:
Can LocalDate include dates BC? If so how do you write them? (dd-mm-yyyy) with a minus on the first y?
Can DatePicker allow the selection of BC dates?
Thanks in advance!
Kind regards,
A
getEra
public Era getEra()
Gets the era applicable at this date.
The official ISO-8601 standard does not define eras, however IsoChronology does. It defines two eras, 'CE' from year one onwards and 'BCE' from year zero backwards. Since dates before the Julian-Gregorian cutover are not in line with history, the cutover between 'BCE' and 'CE' is also not aligned with the commonly used eras, often referred to using 'BC' and 'AD'.
Users of this class should typically ignore this method as it exists primarily to fulfill the ChronoLocalDate contract where it is necessary to support the Japanese calendar system.
The returned era will be a singleton capable of being compared with the constants in IsoChronology using the == operator.
Specified by:
getEra in interface ChronoLocalDate
Returns:
the IsoChronology era constant applicable at this date, not null
source: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html

Why has java.util.Date been deprecated? [duplicate]

When you look at the javadoc of the java.util.Date class, most of the methods are deprecated. Why was this done?
Well, for two related reasons. It was a very poor implementation of the concept of Dates and Times and it was replaced by the Calendar class.
The Calendar class, although an improvement, leaves a lot to be desired as well, so for serious Date/Time work, everyone recommends Joda-Time. Java 8 brings the new java.time.* package, inspired by Joda-Time, defined by JSR-310, and intended to supplant the old Date/Calendar classes.
Edit: In response to the specific question of why the implementation is poor, there are many reasons. The JavaDoc sums it up as follows:
Unfortunately, the API for these functions was not amenable to internationalization.
In addition to this general deficiency (which covers issues like the lack of a Time Zone component as well as the date formatting which is better handled in DateFormat and the inability to have a non-Gregorian calendar representation), there are specific issues which really hurt the Date class, including the fact that year is presented in an offset of 1900 from Common Era year.
Calendar has its own problems, but even as early as JDK 1.1 it was obvious that java.util.Date was not going to cut it. Even though Calendar is arguable the worst JDK API, it has taken until version 7 to attempt to address it.
Date is mutable
Date doesn't have support for time zones
The latter led to it being replaced by Calendar. And the former, combined with the ease-of-use, lead to both being replaced by Joda-Time / JSR-310 (java.time.* package)
They're deprecated because Date was written as fast as possible back in the day when they wanted to rush the JDK out the door.
It turns out the Dates and Calendars are Hard. So, they created the Calendar class, which much more thought, in order to handle the Hard Parts of working with calendars.
They deprecated the Date methods and delegated to Calendar because they didn't want to change the behavior of the existing Date methods, and possibly break existing applications.
Here's a good answer straight from Oracle: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
A long-standing bugbear of Java developers has been the inadequate support for the date and time use cases of ordinary developers.
For example, the existing classes (such as java.util.Date and SimpleDateFormatter) aren’t thread-safe, leading to potential concurrency issues for users—not something the average developer would expect to deal with when writing date-handling code.
Some of the date and time classes also exhibit quite poor API design. For example, years in java.util.Date start at 1900, months start at 1, and days start at 0—not very intuitive.
... java.util.Date represents an instant on the timeline—a wrapper around the number of milli-seconds since the UNIX epoch—but if you call toString(), the result suggests that it has a time zone, causing confusion among developers.
I don't know the official reason why it has been deprecated, but as far as I can tell GregorianCalendarand Joda-Time support operations on dates, meaning that you can add, for instance, a day to a date and have its month and year updated accordingly.
For instance, say you want to compute the day after the current date and today is May 31st; with java.util.Date, you just have getDays() +1, which returns 32, and you have to handle the knowledge that the current month doesn't have 32 days by yourself; with GregorianCalendaror Joda.time, adding a day to May 31st results in an object representing June 1st, hiding the complexity from your sight.

What's the best way to manipulate Dates and Timestamps in Java?

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.

Categories