74457

Calculate number of hours between two dates not including weekends

Question:

Hello i am having issue trying to calculate the amount of hours in a 24 hour day that took place between two different timestamps in java not including weekends.

String timestamp = rs.getString("timestamp"); String timeStamp = new SimpleDateFormat("yyyyMMddHH").format(new Date()); int currentTimeStamp = Integer.parseInt(timeStamp); String orderTime = timestamp.replace("-", ""); String[] splitTimestamp = orderTime.split(" "); String finalTimestamp = splitTimestamp[0] + splitTimestamp[1].substring(0,2); int orderTimeStamp = Integer.parseInt(finalTimestamp);

This currently does work but it includes weekends.

If anyone could help me out I would be very grateful.

This is all done Eastern time zone. Holidays aren't required or needed just weekends.

Answer1:

I find it cleaner with java.util.Calendar, here is an example getting number of hours since March 1st (8am) until current time :

final Calendar first = new Calendar.Builder() .setDate(2016, 2, 1).set(Calendar.AM_PM, 0).set(Calendar.HOUR, 8).build(); final Calendar second = Calendar.getInstance(); int numberOfDays = 0; long numberOfHours = 0; //Get number of full days while(first.get(Calendar.DATE) != second.get(Calendar.DATE)){ if(Calendar.SATURDAY != first.get(Calendar.DAY_OF_WEEK) && Calendar.SUNDAY != first.get(Calendar.DAY_OF_WEEK)){ numberOfDays++; } first.roll(Calendar.DATE, true); } //Get number of hours in the remaining day numberOfHours = TimeUnit.MILLISECONDS .toHours(second.getTimeInMillis() - first.getTimeInMillis()); System.out.println("Difference = " + ( numberOfDays * 24 + numberOfHours ) + " hour(s)");

Answer2:

Avoid old date-time classes

The old date-time classes bundled with the earliest versions of Java are poorly designed, confusing, and troublesome. Avoid java.util.Date/.Calendar and so on.

java.time

Use the java.time framework built into Java 8 and later. Or its backport for Java 7 & 6. See <a href="http://docs.oracle.com/javase/tutorial/datetime/TOC.html" rel="nofollow">Oracle Tutorial</a>.

I have not tried running this code; just off the top of my head. <strong>Never run, never tested.</strong> Might give you a start.

The Question seems to say that we want to assume generic 24-hour days rather than actual days (which can vary in length due to anomalies such as Daylight Saving Time). In the case of generic days, we do not care about time zone. We can use the <a href="http://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html" rel="nofollow">LocalDateTime</a> class.

If the start happens to be on a weekend, move it to the first moment of the following Monday.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHH" ); LocalDateTime start = LocalDateTime.parse( "2016010123" , formatter ); // If on a weekend, move to first moment of Monday. if( start.getDayOfWeek().equals( DayOfWeek.SATURDAY ) { start = start.plusDays( 2 ).toLocalDate().atStartOfDay(); } if( start.getDayOfWeek().equals( DayOfWeek.SUNDAY ) { start = start.plusDays( 1 ).toLocalDate().atStartOfDay(); }

Ditto for the stop. If on weekend, move to first moment of the following Monday.

LocalDateTime stop = LocalDateTime.parse( "2016010723" , formatter ); // If on a weekend, move to first moment of Monday. if( stop.getDayOfWeek().equals( DayOfWeek.SATURDAY ) { stop = stop.plusDays( 2 ).toLocalDate().atStartOfDay(); } if( stop.getDayOfWeek().equals( DayOfWeek.SUNDAY ) { stop = stop.plusDays( 1 ).toLocalDate().atStartOfDay(); }

If the start is the same as stop, we are done: report zero.

if( start.isEqual( stop ) ) { return 0; }

If the start is after the stop, we have an error condition. Throw an exception, try to correct the problem, or report zero, whatever makes sense in your app.

if( start.isAfter( stop ) ) { return 0; // Or consider it a problem, throw exception. }

Let's divide this problem into three parts:

<ul><li>First partial day, </li> <li>Last partial day,</li> <li>Number of whole days in between. </li> </ul>

To represent the partial days, we use the <a href="http://docs.oracle.com/javase/8/docs/api/java/time/Duration.html" rel="nofollow">Duration</a> class. A Duration is a span of time tracked as a total number of seconds plus nanoseconds.

First part runs from start to the first moment of the following day.

LocalDateTime firstMomentOfDayAfterStart = start.toLocalDate().plusDays(1).atStartOfDay(); Duration firstDayDuration = Duration.between( start , firstMomentOfDayAfterStart );

The last partial day runs from first moment of the same day as stop.

LocalDateTime firstMomentOfDayOfStop = stop.toLocalDate().atStartOfDay(); Duration lastDayDuration = Duration.between( firstMomentOfDayOfStop , stop );

We can convert each Duration to a number of hours.

int hoursFirstDay = firstDayDuration.toHours(); int hoursLastDay = lastDayDuration.toHours();

So we have variables defining these spans of time as shown in this text-as-diagram below. Remember these are Half-Open, where the ending of each span is <em>exclusive</em>.

<pre class="lang-none prettyprint-override">[ start > firstMomentOfDayAfterStart ][ firstMomentOfDayAfterStart > firstMomentOfDayOfStop ][ firstMomentOfDayOfStop > stop ]

Now loop through the whole days in between that pair of partial days. Increment day-by-day, testing each successive day for being a weekday or weekend. Keep count of the weekdays we encounter. Use the handy <a href="http://docs.oracle.com/javase/8/docs/api/java/time/DayOfWeek.html" rel="nofollow">DayOfWeek</a> <a href="http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html" rel="nofollow">enum</a> to compare.

int countWeekdays = 0; LocalDateTime firstMomentOfSomeDay = firstMomentOfDayAfterStart while( firstMomentOfSomeDay.isBefore( firstMomentOfDayOfStop ) ) { DayOfWeek dayOfWeek = firstMomentOfSomeDay.getDayOfWeek(); if( dayOfWeek.equals( DayOfWeek.SATURDAY ) || dayOfWeek.equals( DayOfWeek.SUNDAY ) ) { // ignore this day. } else { countWeekdays ++ ; // Tally another weekday. } // Set up the next loop. firstMomentOfSomeDay = firstMomentOfSomeDay.plusDays( 1 ); }

We can use the <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/TimeUnit.html" rel="nofollow">TimeUnit</a> enum to convert the count of whole days to a count of hours. This conversion assumes generic 24-hour days.

int hoursOfWholeDays = TimeUnit.DAYS.toHours( countWeekDays ) ;

Add those all up.

int totalHours = ( hoursFirstDay + hoursOfWholeDays + hoursLastDay ) ;

Done. Return the total hours.

return totalHours ;

If your data often includes long periods of time then you might consider optimizing performance by detecting a Monday and calculating number of whole weeks. I assume for tracking orders in a business scenario, the intervals are for a small number of days. So this optimization is not likely to be significant.

<h2>EnumSet</h2>

You can replace the line:

if( dayOfWeek.equals( DayOfWeek.SATURDAY ) || dayOfWeek.equals( DayOfWeek.SUNDAY ) )…

…with an <a href="https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html" rel="nofollow">EnumSet</a>.

Set<DayOfWeek> weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY ) ; … if( weekend.contains( dayOfWeek ) ) …

Temporal Adjustor

See <a href="https://stackoverflow.com/a/34955818/642706" rel="nofollow">my answer to another Question</a> for more info on detecting weekends using the <a href="http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/Temporals.html#nextWorkingDay--" rel="nofollow">nextWorkingDay</a> and previousWorkingDay methods of the <a href="http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/Temporals.html" rel="nofollow">Temporals</a> class. This class is found in the <a href="http://www.threeten.org/threeten-extra/" rel="nofollow">ThreeTen-Extra</a> project that extends the java.time framework.

Furthermore, that class docs suggests it is relatively easy to write your own temporal adjustor to suit your particular business rules.

Answer3:

You could do something like this:

Date date1 = new Date(2016, 3, 21), date2 = new Date(2016, 4, 9); int oneHour = 1000 * 60 * 60; //Note that this rounds down the number of hours/days int hours = (int)((date2.getTime() - date1.getTime()) / oneHour); int days = hours / 24; int day1, day2; //set the values of day: [Sun=0, Mon=1, Tue=2, Wed=3, Thur=4, Fri=5, Sat=6] //date.getDay() is supposed to do that, but it's deprecated int nWEdays = days/7*2; if(day2-day1 < 0) nWEdays += 2; else { if(day1 == 0 || day1 == 6) nWEdays++; else if(day2 == 0 || day2 == 6) nWEdays++; } int weekendHours = hours - nWEdays*24;

Recommend

  • Disable Windows Phone in Phonegap Build
  • Retrieving the associated shared service provider's name?
  • How to test Date functions that should return a specific date
  • error LNK2001: unresolved external symbol _IID_IDirectDraw2
  • Rake tasks seem to ignore database.yml configuration
  • Python: ctypes + C malloc error. C memory problem or Python/ctypes problem?
  • Splitting a csv file into panda dataframe by multiple columns
  • How to upload video to Vimeo through their api?
  • Sorting parallel arrays in javascript
  • Performing way to limit double accuracy
  • Why do native C++ projects have a TargetFrameworkVersion?
  • Weird LEFT OUTER JOIN on Includes eager loading of rails 3
  • How many Vertica Databases can run on a Host in the same time?
  • How do you create a Fuseki SPARQL server using the Apache Jena Java API?
  • What is the use of a session store?
  • jquery validation - waiting for remote check to complete
  • MySQL performance when updating row with FK
  • Simple linked list-C
  • Sending keystrokes/mouse clicks to a Java program with Autohotkey
  • How do I display a dialog that asks the user multi-choice questıon using tkInter?
  • Center align outputs in ipython notebook
  • how does System.Web.HttpRequest::PathInfo work?
  • Scala multiline string placeholder
  • Does Mobilefirst provide a provision to access web services directly?
  • How to run “Deployd” on port 80 instead of port 5000 in webserver.
  • Exchange data b/w iOS devices using Bluetooth 4.0
  • Cross-Platform Protobuf Serialization
  • How to apply VCL Styles to DLL-based forms in Inno Setup?
  • ActionScript 2 vs ActionScript 3 performance
  • How can I estimate amount of memory left with calling System.gc()?
  • Apache 2.4 - remove | delete | uninstall
  • How to format a variable of double type
  • Proper folder structure for lots of source files
  • Acquiring multiple attributes from .xml file in c#
  • coudnt use logback because of log4j
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • How can I remove ASP.NET Designer.cs files?
  • JaxB to read class hierarchy
  • java string with new operator and a literal
  • Net Present Value in Excel for Grouped Recurring CF