Ajouter des heures d’ouverture à Java DateTime

Pour un système de suivi des problèmes, je dois calculer le temps de réponse d’une demande. Le minuteur pour le temps de réponse ne devrait fonctionner que pendant les heures ouvrables. Quel algorithme / bibliothèque dois-je utiliser pour cette tâche? (Bien sûr, je connais Joda-Time ou ObjectLab Kit, mais je n’ai rien trouvé qui puisse m’aider dans ma tâche. Est-ce que je manque quelque chose?)

Exemple:

  • Heures d’ouverture: de 9h à 17h (8 heures par jour)
  • Temps de réponse maximum: 16 heures

La méthode peut ressembler à quelque chose comme:

DateTime calculateResponseTime(DateTime issueReportedAt) 

Je vais donner quelques entrées et résultats possibles à titre d’exemple:

  • Lun., 2011-09-19, 13:00 -> mer., 2011-09-21, 13:00
  • Lun, 2011-09-19, 18h05 -> Jeu, 2011-09-22, 9h00
  • Ven, 2011-09-23, 14h00 -> Mardi, 2011-09-27, 14h00

Vous pouvez consulter le calendrier professionnel jBPM .

Une autre bibliothèque vous permet de configurer les jours fériés, mais elle n’a aucune notion des heures ouvrables.

Je pense que ce que Oleg proposait était de jeter un regard sur la manière dont jBPM implémente cette fonctionnalité pour trouver une source d’inspiration pour coder votre propre solution. Voici ma réponse empruntant beaucoup à la source que j’ai trouvée en effectuant une recherche de code dans Google .

Cela ne tient pas compte des jours fériés, mais je vais laisser cela comme un exercice pour vous. Puis-je suggérer d’utiliser un service Web pour mettre à jour chaque année une liste de dates restreinte? Bonne chance!

  int fromHour = 9; int fromMinute = 0; int toHour = 17; int toMinute = 0; long maxResponseTime = 16; Date calculateResponseTime(Date issueReportedAt, long responseHours) { Date end = null; Calendar responseTime = Calendar.getInstance(); responseTime.setTime(issueReportedAt); int hourOfDay = responseTime.get(Calendar.HOUR_OF_DAY); int dayOfWeek = responseTime.get(Calendar.DAY_OF_WEEK); if (hourOfDay < fromHour) { responseTime.set(Calendar.HOUR, fromHour); } if (hourOfDay >= toHour || dayOfWeek == 1) { responseTime.add(Calendar.DATE, 1); responseTime.set(Calendar.HOUR_OF_DAY, fromHour); responseTime.set(Calendar.MINUTE, fromMinute); } else if (dayOfWeek == 7) { responseTime.add(Calendar.DATE, 2); responseTime.set(Calendar.HOUR_OF_DAY, fromHour); responseTime.set(Calendar.MINUTE, fromMinute); } int hour = responseTime.get(Calendar.HOUR_OF_DAY); int minute = responseTime.get(Calendar.MINUTE); long dateMilliseconds = ((hour * 60) + minute) * 60 * 1000; long dayPartEndMilleseconds = ((toHour * 60) + toMinute) * 60 * 1000; long millisecondsInThisDayPart = dayPartEndMilleseconds - dateMilliseconds; long durationMilliseconds = responseHours * 60 * 60 * 1000; if (durationMilliseconds < millisecondsInThisDayPart) { end = new Date(responseTime.getTimeInMillis() + durationMilliseconds); } else { long remainder = (durationMilliseconds - millisecondsInThisDayPart) / 60 / 60 / 1000; Date dayPartEndDate = new Date(responseTime.getTimeInMillis() + durationMilliseconds); responseTime.setTime(dayPartEndDate); end = calculateResponseTime(responseTime.getTime(), remainder); } return end; } @Test public void testCalculateResponseTime() { Calendar issueReportedAt = Calendar.getInstance(); Calendar expectedResponseTime = Calendar.getInstance(); issueReportedAt.set(2011, 8, 19, 13, 0, 0); expectedResponseTime.set(2011, 8, 21, 13, 0, 0); assertTrue(expectedResponseTime.getTime().equals( calculateResponseTime(issueReportedAt.getTime(), maxResponseTime))); issueReportedAt.set(2011, 8, 19, 18, 5, 0); expectedResponseTime.set(2011, 8, 22, 9, 0, 0); assertTrue(expectedResponseTime.getTime().equals( calculateResponseTime(issueReportedAt.getTime(), maxResponseTime))); issueReportedAt.set(2011, 8, 23, 14, 0, 0); expectedResponseTime.set(2011, 8, 27, 14, 0, 0); assertTrue(expectedResponseTime.getTime().equals( calculateResponseTime(issueReportedAt.getTime(), maxResponseTime))); } 

Vous devez append un cas supplémentaire à la partie normalisation de la réponse Anils, car si le problème est signalé le vendredi à 10h00 et que la heure de réponse est 10, que lors du prochain appel récursif, issueReportedAt sera vendredi à 22 heures. être normalisé au samedi à 21h00, la sorcière est également invalide.

 if (hourOfDay >= WorkingHours.TO_HOUR && dayOfWeek == Calendar.FRIDAY) { responseTime.add(Calendar.DATE, 3); responseTime.set(Calendar.HOUR_OF_DAY, WorkingHours.FROM_HOUR); responseTime.set(Calendar.MINUTE, WorkingHours.FROM_MINUTE); } 

Le code ci-dessous résout le problème

 public static Date addBusinessHours(Calendar startDate, int hours, int workingHourStart, int workingHourEnd){ System.out.println("Entering: Date Time " + startDate.getTime() + " | Remaining Hours: "+ hours + " | Working hours ("+workingHourStart+"-"+workingHourEnd+")"); if(hours == 0){ return startDate.getTime(); } int hourOfDay = startDate.get(Calendar.HOUR_OF_DAY); if(startDate.get(Calendar.MINUTE) > 0){ hourOfDay = hourOfDay +1; } int dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK); if(dayOfWeek == Calendar.SATURDAY){ startDate.add(Calendar.DATE, 2); startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); addBusinessHours(startDate, hours, workingHourStart, workingHourEnd); } if(dayOfWeek == Calendar.SUNDAY){ startDate.add(Calendar.DATE, 1); startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); addBusinessHours(startDate, hours, workingHourStart, workingHourEnd); } if(dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY){ if(hourOfDay < workingHourStart){ startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); hourOfDay = startDate.get(Calendar.HOUR_OF_DAY); dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK); addBusinessHours(startDate, hours, workingHourStart, workingHourEnd); } else if(hourOfDay >= workingHourEnd){ startDate.add(Calendar.DATE, 1); startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); hourOfDay = startDate.get(Calendar.HOUR_OF_DAY); dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK); addBusinessHours(startDate, hours, workingHourStart, workingHourEnd); } else if(hourOfDay >= workingHourStart && hourOfDay < workingHourEnd){ if(hours+hourOfDay <= workingHourEnd){ startDate.add(Calendar.HOUR_OF_DAY, hours); return startDate.getTime(); }else{ //System.out.println("¤¤" + startDate.getTime() ); startDate.add(Calendar.DATE, 1); //System.out.println("¤¤" + startDate.getTime() ); startDate.set(Calendar.HOUR_OF_DAY, workingHourStart); startDate.set(Calendar.MINUTE, 0); startDate.set(Calendar.SECOND, 0); //System.out.println("¤¤" + startDate.getTime() ); System.out.println("##"+hours+ "##"+ workingHourEnd + "##" + hourOfDay); int remaining_hours = hours - (workingHourEnd - hourOfDay); addBusinessHours(startDate, remaining_hours, workingHourStart, workingHourEnd); } } } return startDate.getTime(); }