Comment puis-je calculer une période en Java et formater la sortie?

Je veux prendre deux fois (en secondes depuis l’époque) et montrer la différence entre les deux dans des formats tels que:

  • 2 minutes
  • 1 heure 15 minutes
  • 3 heures, 9 minutes
  • il y a 1 minute
  • Il y a 1 heure et 2 minutes

Comment puis-je accomplir cela??

Puisque tout le monde crie “YOODAA !!!” mais personne ne publie un exemple concret, voici ma consortingbution.

Vous pouvez aussi le faire avec Joda-Time . Utilisez Period pour représenter une période. Pour formater le point dans la représentation humaine souhaitée, utilisez PeriodFormatter que vous pouvez créer avec PeriodFormatterBuilder .

Voici un exemple de coup d’envoi:

 DateTime myBirthDate = new DateTime(1978, 3, 26, 12, 35, 0, 0); DateTime now = new DateTime(); Period period = new Period(myBirthDate, now); PeriodFormatter formatter = new PeriodFormatterBuilder() .appendYears().appendSuffix(" year, ", " years, ") .appendMonths().appendSuffix(" month, ", " months, ") .appendWeeks().appendSuffix(" week, ", " weeks, ") .appendDays().appendSuffix(" day, ", " days, ") .appendHours().appendSuffix(" hour, ", " hours, ") .appendMinutes().appendSuffix(" minute, ", " minutes, ") .appendSeconds().appendSuffix(" second", " seconds") .printZeroNever() .toFormatter(); Ssortingng elapsed = formatter.print(period); System.out.println(elapsed + " ago"); 

Beaucoup plus clair et concis, n’est-ce pas?

Ceci imprime maintenant

 32 années, 1 mois, 1 semaine, 5 jours, 6 heures, 56 minutes, 24 secondes

(Toux, vieux, toux)

  Date start = new Date(1167627600000L); // JANUARY_1_2007 Date end = new Date(1175400000000L); // APRIL_1_2007 long diffInSeconds = (end.getTime() - start.getTime()) / 1000; long diff[] = new long[] { 0, 0, 0, 0 }; /* sec */diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds); /* min */diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds; /* hours */diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds; /* days */diff[0] = (diffInSeconds = (diffInSeconds / 24)); System.out.println(Ssortingng.format( "%d day%s, %d hour%s, %d minute%s, %d second%s ago", diff[0], diff[0] > 1 ? "s" : "", diff[1], diff[1] > 1 ? "s" : "", diff[2], diff[2] > 1 ? "s" : "", diff[3], diff[3] > 1 ? "s" : "")); 

Yup a réveillé les morts que j’ai, mais voici mon implémentation améliorée basée sur le code posté par @mtim, car ce fil passe presque au-dessus des recherches, alors je joue avec le creux endormi,

  public static Ssortingng getFriendlyTime(Date dateTime) { SsortingngBuffer sb = new SsortingngBuffer(); Date current = Calendar.getInstance().getTime(); long diffInSeconds = (current.getTime() - dateTime.getTime()) / 1000; /*long diff[] = new long[]{0, 0, 0, 0}; /* sec * diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds); /* min * diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds; /* hours * diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds; /* days * diff[0] = (diffInSeconds = (diffInSeconds / 24)); */ long sec = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds); long min = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds; long hrs = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds; long days = (diffInSeconds = (diffInSeconds / 24)) >= 30 ? diffInSeconds % 30 : diffInSeconds; long months = (diffInSeconds = (diffInSeconds / 30)) >= 12 ? diffInSeconds % 12 : diffInSeconds; long years = (diffInSeconds = (diffInSeconds / 12)); if (years > 0) { if (years == 1) { sb.append("a year"); } else { sb.append(years + " years"); } if (years <= 6 && months > 0) { if (months == 1) { sb.append(" and a month"); } else { sb.append(" and " + months + " months"); } } } else if (months > 0) { if (months == 1) { sb.append("a month"); } else { sb.append(months + " months"); } if (months <= 6 && days > 0) { if (days == 1) { sb.append(" and a day"); } else { sb.append(" and " + days + " days"); } } } else if (days > 0) { if (days == 1) { sb.append("a day"); } else { sb.append(days + " days"); } if (days <= 3 && hrs > 0) { if (hrs == 1) { sb.append(" and an hour"); } else { sb.append(" and " + hrs + " hours"); } } } else if (hrs > 0) { if (hrs == 1) { sb.append("an hour"); } else { sb.append(hrs + " hours"); } if (min > 1) { sb.append(" and " + min + " minutes"); } } else if (min > 0) { if (min == 1) { sb.append("a minute"); } else { sb.append(min + " minutes"); } if (sec > 1) { sb.append(" and " + sec + " seconds"); } } else { if (sec <= 1) { sb.append("about a second"); } else { sb.append("about " + sec + " seconds"); } } sb.append(" ago"); /*String result = new String(String.format( "%d day%s, %d hour%s, %d minute%s, %d second%s ago", diff[0], diff[0] > 1 ? "s" : "", diff[1], diff[1] > 1 ? "s" : "", diff[2], diff[2] > 1 ? "s" : "", diff[3], diff[3] > 1 ? "s" : ""));*/ return sb.toSsortingng(); } 

Cela peut évidemment être amélioré. En gros, il essaie de rendre la durée plus conviviale, mais il y a quelques limitations, c.-à-d. qu’il se comporterait étrangement si le temps passé (paramètre) est à venir et limité aux jours, heures et secondes seulement (mois et années non) manipulé, pour que quelqu’un d’autre puisse ;-).

les sorties d’échantillon sont:

  • il y a environ une seconde
  • Il y a 8 minutes et 34 secondes
  • il y a une heure et 4 minutes
  • il y a un jour
  • Il y a 29 jours
  • il y a un an et 3 mois

, acclamations: D

EDIT: supporte maintenant les mois et les années: P

Je vous recommande de regarder HumanTime

Éviter les anciennes classes date-heure

Les autres réponses peuvent être correctes mais sont obsolètes. Les anciennes classes de date-heure gênantes de Java sont désormais héritées, supplantées par les classes java.time.

De même, le projet Joda-Time , maintenant en mode maintenance , conseille la migration vers les classes java.time .

Utiliser java.time

Instant

deux fois (en secondes depuis l’époque)

Dans java.time, nous représentons des moments sur la timeline dans UTC en tant Instant . Je suppose que votre époque est la même que celle de java.time, le premier moment de 1970 en UTC ( 1970-01-01T00:00:00Z ). Notez qu’un Instant a une résolution de nanosecondes. Une méthode d’usine de commodité construit un Instant partir de secondes entières, comme demandé dans la question.

 Instant start = Instant.ofEpochSecond( … ); Instant stop = Instant.ofEpochSecond( … ); 

Ici, nous utilisons le moment actuel et quelques minutes plus tard.

 Instant start = Instant.now() ; Instant stop = start.plusSeconds( TimeUnit.MINUTES.toSeconds( 7L ) ) ; // Seven minutes as a number of seconds. 

Duration

Dans java.time, une période de temps indépendante de la chronologie est représentée de deux manières. Pour les années-mois-jours, nous avons Period . Pendant des heures-minutes-secondes, nous avons la Duration .

 Duration duration = Duration.between( start , stop ); 

À moitié ouvert

Le temps écoulé est calculé avec l’approche Half-Open. Dans cette approche, le début est inclusif alors que la fin est exclusive . Cette approche est couramment utilisée dans le travail de date-heure. Je crois que l’utilisation de cette approche de manière cohérente à travers votre base de code aidera à éliminer les erreurs et les malentendus dus aux ambiguïtés et facilitera la charge cognitive de votre programmation.

ISO 8601

La norme ISO 8601 définit de nombreux formats pratiques pour représenter les valeurs date-heure sous forme de texte. Ces formats sont conçus pour éviter toute ambiguïté, être faciles à parsingr par machine et être intuitifs pour être lus par des personnes de différentes cultures.

Les classes java.time utilisent ces formats par défaut lors de l’parsing et de la génération de chaînes.

Pendant un laps de temps non attaché à la chronologie, la norme définit un format de PnYnMnDTnHnMnSP marque le début et T sépare les années-mois-jours des heures-minutes-secondes. Donc, une heure et demie est PT1H30M .

Dans notre exemple de code utilisant sept minutes:

 Ssortingng outputStandard = duration.toSsortingng(); 

PT7M

Voir l’exemple de code ci-dessus exécuté en direct sur IdeOne.com .

Je suggère de conserver ces formats chaque fois que possible, notamment lors de l’échange ou de la sérialisation de données date-heure, mais également de l’utilisation dans une interface utilisateur, le cas échéant, et que vos utilisateurs peuvent être formés pour les utiliser.

Je recommande de ne jamais utiliser le format d’horloge (ex: 01h30 pour une heure et demie) car ce format est complètement ambigu avec une heure du jour.

Récupération de pièces pour créer une chaîne

Si vous devez préciser la durée, comme indiqué dans la Question, vous devrez créer le texte vous-même.

  • Pour Period , appelez getYears , getMonths et getDays pour récupérer chaque partie.
  • Curieusement, la classe Duration ne possédait pas de tels éléments dans Java 8 , mais elle les gagnait dans Java 9 et les toDaysPart ultérieures: toDaysPart , toHoursPart , toMinutesPart , toSecondsPart et toNanosPart .

Un exemple de code, simple et élémentaire pour vous aider à démarrer.

 int days = duration.toDaysPart() ; int hours = duration.toHoursPart() ; int minutes = duration.toMinutesPart() ; int seconds = duration.toSecondsPart() ; int nanos = duration.toNanosPart() ; SsortingngBuilder sb = new SsortingngBuilder( 100 ); if( days != 0 ) { sb.append( days + " days" ) ; }; if( hours != 0 ) { sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ; // Append comma if any existing text. sb.append( hours + " hours" ) ; }; if( minutes != 0 ) { sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ; // Append comma if any existing text. sb.append( minutes + " minutes" ) ; }; if( seconds != 0 ) { sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ; // Append comma if any existing text. sb.append( seconds + " seconds" ) ; }; if( nanos != 0 ) { sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ; // Append comma if any existing text. sb.append( nanos + " nanos" ) ; }; Ssortingng output = sb.toSsortingng(); 

Ou peut-être pourriez-vous écrire un code plus lisse en utilisant DateTimeFormatterBuilder de la manière indiquée avec Joda-Time dans la réponse de Balus C.


À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes de date / heure héritées telles que java.util.Date , Calendar et SimpleDateFormat .

Le projet Joda-Time , maintenant en mode maintenance , conseille la migration vers les classes java.time .

Pour en savoir plus, consultez le didacticiel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Où obtenir les classes java.time?

  • Java SE 8 et SE 9 et versions ultérieures
    • Intégré
    • Partie de l’API Java standard avec une implémentation intégrée.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et SE 7
    • Une grande partie de la fonctionnalité java.time est transférée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android
    • Le projet ThreeTenABP adapte ThreeTen-Backport (mentionné ci-dessus) pour Android en particulier.
    • Voir Comment utiliser ThreeTenABP… .

Le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts futurs à java.time. Vous pouvez trouver ici des classes utiles telles que Interval , YearWeek , YearQuarter , etc.

Je ne suis pas un expert en Java, mais vous pouvez faire t1-t2 = t3 (en secondes), puis diviser cela par 60, vous donner des minutes, par un autre 60 vous donnerait des secondes. Il suffit ensuite de déterminer le nombre de divisions dont vous avez besoin.

J’espère que cela aide.

Si vos délais dépassent les limites de l’heure d’été, voulez-vous indiquer le nombre de jours?

Par exemple, 23h00 à 23h00 le lendemain est toujours un jour mais peut être 23, 24 ou 25 heures selon que vous traversez une transition d’heure d’été.

Si cela vous intéresse, assurez-vous de le prendre en compte dans votre choix.

un code qui joue avec le formatage de la date … et le temps passé.

 SimpleDateFormat curFormater = new SimpleDateFormat("EEE, dd MMM yyyy kk:mm:ss"); try { Date dateObj = curFormater.parse(pubDate); SimpleDateFormat postFormater = new SimpleDateFormat("MMMM dd, yyyy ss:mm:hh"); Ssortingng newDateStr = postFormater.format(dateObj); Log.v("THE NEW DATE IS",newDateStr); long pubdateinmilis = dateObj.getTime(); pubDate = (Ssortingng) DateUtils.getRelativeTimeSpanSsortingng(pubdateinmilis, System.currentTimeMillis(),DateUtils.HOUR_IN_MILLIS,DateUtils.FORMAT_ABBREV_RELATIVE); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } 

Je commence toujours par Joda Time . Travailler avec les dates et les heures en Java est toujours “amusant”, mais Joda Time prend le dessus.

Ils ont des classes d’intervalle et de durée qui font la moitié de ce que vous recherchez. Pas sûr si elles ont une fonction pour la sortie dans un format lisible cependant. Je continuerai à chercher.

HTH

La classe Calendar peut gérer la plupart des mathématiques liées à la date. Vous devrez obtenir le résultat de compareTo et sortir le format vous-même. Il n’y a pas de bibliothèque standard qui fait exactement ce que vous cherchez, bien qu’il puisse y avoir une bibliothèque tierce.

OK, après un bref aperçu de l’API, il semble que vous puissiez faire ce qui suit: –

  1. créer des ReadableInstants représentant l’heure de début et l’heure de fin.
  2. Utilisez Hours.hoursBetween pour obtenir le nombre d’heures
  3. utiliser Minutes.minutesEntre pour obtenir le nombre de minutes
  4. utiliser le mod 60 sur les minutes pour obtenir les minutes restantes
  5. et voilà!

HTH

La solution de “Abduliam Rehmanius” semble plutôt intéressante, ou vous pouvez utiliser une bibliothèque ci-dessus ou créer de nouvelles choses simples, reportez-vous à la solution JS ici: http://www.datejs.com/ . Ce n’est pas difficile de se transformer en Java lang 🙂

J’espère que mon lien est utile pour vous!