Pour info, le format que vous semblez décrire est Durationdéfini dans la norme sensible, ISO 8601 : PnYnMnDTnHnMnSoù Psignifie "Période" et marque le début, Tsépare la partie date de la partie heure, et entre les occurrences facultatives d'un nombre avec un seul -abréviation de lettre. Par exemple, PT4H30M= quatre heures et demie.
Basil Bourque
1
Si tout le reste échoue, il est très simple de le faire vous-même. Utilisez simplement des applications successives de %et /pour diviser le nombre en parties. Presque plus facile que certaines des réponses proposées.
Hot Licks
@HotLicks Laissez-le aux méthodes de bibliothèque pour un code beaucoup plus propre et plus clair que d'utiliser /et %.
Ole VV
Oui, au cours des 8 années écoulées depuis que j'ai posé cette question (!), Je suis passé à joda time qui convient très bien à mon cas d'utilisation
phatmanace
@phatmanace Le projet Joda-Time est maintenant en mode maintenance et conseille la migration vers les classes java.time intégrées à Java 8 et versions ultérieures.
Il ressort de la réponse ci-dessous qu'une instance de Period peut être créée directement, sans créer d'abord une instance de Duration, puis la convertir en Period. Par exemple, période période = nouvelle période (millisecondes); Chaîne formatée = formatter.print (point);
Basil Vandegriend
7
Méfiez-vous de cette conversion "duration.toPeriod ()". Si la durée est assez grande, la portion du jour restera à 0. La portion des heures continuera de croître. Vous obtiendrez 25h10m23s mais jamais le "d". La raison en est qu'il n'y a pas de moyen totalement correct de convertir des heures en jours de la manière stricte de Joda. Dans la plupart des cas, si vous comparez deux instants et que vous souhaitez l'imprimer, vous pouvez faire une nouvelle période (t1, t2) au lieu d'une nouvelle durée (t1, t2) .toPeriod ().
Boon le
@Boon savez-vous comment convertir la durée en période par rapport aux jours? J'utilise la durée à partir de laquelle je peux remplacer la seconde dans mon sur ma minuterie. Réglage de l'événement PeriodType.daysTime()ou .standard()n'a pas aidé
murt
4
@murt Si vous voulez vraiment, et pouvez accepter la définition standard d'un jour, alors vous pouvez "formatter.print (duration.toPeriod (). normalizedStandard ())" dans le code ci-dessus. S'amuser!
Boon
74
J'ai construit une solution simple, en utilisant Java 8 Duration.toString()et un peu de regex:
Vous ne devez jamais vous fier à la sortie de toStrong () car cela peut changer dans d'autres versions.
Weltraumschaf
14
@Weltraumschaf il est peu probable que cela change, car il est spécifié dans le javadoc
aditsu quit parce que SE est EVIL
9
@Weltraumschaf Peu susceptible de changer car la sortie de Duration::toStringest formatée selon la norme ISO 8601 bien définie et bien utilisée .
Basil Bourque
1
Si vous ne voulez pas de fractions, ajoutez .replaceAll("\\.\\d+", "")avant l'appel à toLowerCase().
zb226
1
@Weltraumschaf Votre point de vue est généralement correct et je ne me fierais pas moi-même à la sortie toString () de la plupart des classes. Mais dans ce cas très spécifique, la définition de la méthode indique que sa sortie suit la norme ISO-8601, comme vous pouvez le voir dans le Javadoc de la méthode . Donc ce n'est pas un détail d'implémentation comme dans la plupart des classes, donc pas quelque chose que je m'attendrais à ce qu'un langage aussi mature que Java change comme ça,
lucasls
13
Apache commons-lang fournit une classe utile pour y parvenir également DurationFormatUtils
JodaTime a une Periodclasse qui peut représenter de telles quantités, et peut être rendue (via IsoPeriodFormat) au format ISO8601 , par PT4D1H3M5Sexemple
Period period =newPeriod(millis);String formatted =ISOPeriodFormat.standard().print(period);
Si ce format n'est pas celui que vous souhaitez, PeriodFormatterBuildervous permet d'assembler des mises en page arbitraires, y compris votre style C # 4d1h3m5s.
Le projet ThreeTen-Extra , qui est maintenu par Stephen Colebourne, l'auteur de JSR 310, java.time et Joda-Time , a une AmountFormatsclasse qui fonctionne avec les classes de date standard Java 8. C'est assez verbeux cependant, sans option pour une sortie plus compacte.
Duration d =Duration.ofMinutes(1).plusSeconds(9).plusMillis(86);System.out.println(AmountFormats.wordBased(d,Locale.getDefault()));
Wow, bon à savoir, je n'ai pas vu cette fonctionnalité. A un défaut majeur cependant: il manque la virgule d'Oxford .
Basil Bourque
4
@BasilBourque La virgule d'Oxford est typique des États-Unis, mais curieusement pas pour le Royaume-Uni. Ma lib Time4J (qui a une bien meilleure internationalisation) prend en charge cette distinction dans la classe net.time4j.PrettyTime et permet également de contrôler la sortie compacte si vous le souhaitez.
Une alternative à l'approche constructeur de Joda-Time serait une solution basée sur des modèles . Ceci est offert par ma bibliothèque Time4J . Exemple utilisant la classe Duration.Formatter (ajout de quelques espaces pour plus de lisibilité - la suppression des espaces donnera le style C # souhaité):
IsoUnit unit =ClockUnit.MILLIS;Duration<IsoUnit> dur =// normalized duration with multiple componentsDuration.of(123456, unit).with(Duration.STD_PERIOD);Duration.Formatter<IsoUnit> f =// create formatter/parser with optional millisDuration.Formatter.ofPattern("D'd' h'h' m'm' s[.fff]'s'");System.out.println(f.format(dur));// output: 0d 0h 2m 3.456s
Ce formateur peut également imprimer des durées de java.time-API (cependant, les fonctionnalités de normalisation de ce type sont moins puissantes):
L'espoir de l'OP selon lequel "123456 ms en tant que long serait imprimé comme 4d1h3m5s" est calculé d'une manière manifestement erronée. Je suppose que la négligence est une raison. Le même formateur de durée défini ci-dessus peut également être utilisé comme analyseur. Le code suivant montre que "4d1h3m5s" correspond plutôt à 349385000 = 1000 * (4 * 86400 + 1 * 3600 + 3 * 60 + 5):
Une autre méthode consiste à utiliser la classe net.time4j.PrettyTime(qui est également utile pour la sortie localisée et l'impression des heures relatives telles que "hier", "dimanche prochain", "il y a 4 jours", etc.):
String s =PrettyTime.of(Locale.ENGLISH).print(dur,TextWidth.NARROW);System.out.println(s);// output: 2m 3s 456ms
s =PrettyTime.of(Locale.ENGLISH).print(dur,TextWidth.WIDE);System.out.println(s);// output: 2 minutes, 3 seconds, and 456 milliseconds
s =PrettyTime.of(Locale.UK).print(dur,TextWidth.WIDE);System.out.println(s);// output: 2 minutes, 3 seconds and 456 milliseconds
La largeur du texte contrôle si les abréviations sont utilisées ou non. Le format de la liste peut également être contrôlé en choisissant les paramètres régionaux appropriés. Par exemple, l'anglais standard utilise la virgule Oxform, contrairement au Royaume-Uni. La dernière version v5.5 de Time4J prend en charge plus de 90 langues et utilise des traductions basées sur le référentiel CLDR (une norme de l'industrie).
ce PrettyTime est bien meilleur que celui de l'autre réponse! dommage que je ne l'ai pas trouvé en premier.
ycomp
Je ne sais pas pourquoi il y a maintenant deux votes négatifs pour cette solution qui fonctionne bien, j'ai donc décidé d'étendre la réponse en donnant plus d'exemples également sur l'analyse (le contraire du formatage) et de mettre en évidence la mauvaise attente de l'OP.
avec Durée d1 = Durée. des jours (0); d1 = d1.plusHours (47); d1 = d1.plusMinutes (124); d1 = d1.plusSeconds (124); System.out.println (String.format ("% s jours et% sh% sm% 1.0fs", d1.toDays (), d1.toHours () - TimeUnit.DAYS.toHours (d1.toDays ()), d1 .toMinutes () - TimeUnit.HOURS.toMinutes (d1.toHours ()), d1.toSeconds () - TimeUnit.MINUTES.toSeconds (d1.toMinutes ())));
erickdeoliveiraleal
@erickdeoliveiraleal Merci de l'avoir signalé. Je pense que j'écrivais à l'origine le code de groovy, donc cela aurait pu fonctionner dans ce langage. Je l'ai corrigé pour java maintenant.
Torsten
3
Je me rends compte que cela peut ne pas correspondre exactement à votre cas d'utilisation, mais PrettyTime peut être utile ici.
PrettyTime p =newPrettyTime();System.out.println(p.format(newDate()));//prints: “right now”System.out.println(p.format(newDate(1000*60*10)));//prints: “10 minutes from now”
Duration
défini dans la norme sensible, ISO 8601 :PnYnMnDTnHnMnS
oùP
signifie "Période" et marque le début,T
sépare la partie date de la partie heure, et entre les occurrences facultatives d'un nombre avec un seul -abréviation de lettre. Par exemple,PT4H30M
= quatre heures et demie.%
et/
pour diviser le nombre en parties. Presque plus facile que certaines des réponses proposées./
et%
.Réponses:
Heure Joda a un très bon moyen de le faire en utilisant un PeriodFormatterBuilder .
Victoire rapide:
PeriodFormat.getDefault().print(duration.toPeriod());
par exemple
la source
PeriodType.daysTime()
ou.standard()
n'a pas aidéJ'ai construit une solution simple, en utilisant Java 8
Duration.toString()
et un peu de regex:Le résultat ressemblera à:
Si vous ne voulez pas d'espaces entre les deux, supprimez simplement
replaceAll
.la source
Duration::toString
est formatée selon la norme ISO 8601 bien définie et bien utilisée ..replaceAll("\\.\\d+", "")
avant l'appel àtoLowerCase()
.Apache commons-lang fournit une classe utile pour y parvenir également DurationFormatUtils
par exemple
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
=> 4: 16: 02.000 (H: m: s.millis)DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
=> P0Y0M0DT4H16M2.000S, cf. ISO8601la source
JodaTime a une
Period
classe qui peut représenter de telles quantités, et peut être rendue (viaIsoPeriodFormat
) au format ISO8601 , parPT4D1H3M5S
exempleSi ce format n'est pas celui que vous souhaitez,
PeriodFormatterBuilder
vous permet d'assembler des mises en page arbitraires, y compris votre style C #4d1h3m5s
.la source
new Period(millis).toString()
utilise leISOPeriodFormat.standard()
par défaut.Avec Java 8, vous pouvez également utiliser la
toString()
méthode dejava.time.Duration
pour le formater sans bibliothèques externes en utilisant une représentation basée sur ISO 8601 secondes telle que PT8H6M12.345S.la source
Voici comment vous pouvez le faire en utilisant du code JDK pur:
la source
org.threeten.extra.AmountFormats.wordBased
Le projet ThreeTen-Extra , qui est maintenu par Stephen Colebourne, l'auteur de JSR 310, java.time et Joda-Time , a une
AmountFormats
classe qui fonctionne avec les classes de date standard Java 8. C'est assez verbeux cependant, sans option pour une sortie plus compacte.1 minute, 9 seconds and 86 milliseconds
la source
Java 9+
2 j 1h 6m 4s
la source
Une alternative à l'approche constructeur de Joda-Time serait une solution basée sur des modèles . Ceci est offert par ma bibliothèque Time4J . Exemple utilisant la classe Duration.Formatter (ajout de quelques espaces pour plus de lisibilité - la suppression des espaces donnera le style C # souhaité):
Ce formateur peut également imprimer des durées de
java.time
-API (cependant, les fonctionnalités de normalisation de ce type sont moins puissantes):L'espoir de l'OP selon lequel "123456 ms en tant que long serait imprimé comme 4d1h3m5s" est calculé d'une manière manifestement erronée. Je suppose que la négligence est une raison. Le même formateur de durée défini ci-dessus peut également être utilisé comme analyseur. Le code suivant montre que "4d1h3m5s" correspond plutôt à
349385000 = 1000 * (4 * 86400 + 1 * 3600 + 3 * 60 + 5)
:Une autre méthode consiste à utiliser la classe
net.time4j.PrettyTime
(qui est également utile pour la sortie localisée et l'impression des heures relatives telles que "hier", "dimanche prochain", "il y a 4 jours", etc.):La largeur du texte contrôle si les abréviations sont utilisées ou non. Le format de la liste peut également être contrôlé en choisissant les paramètres régionaux appropriés. Par exemple, l'anglais standard utilise la virgule Oxform, contrairement au Royaume-Uni. La dernière version v5.5 de Time4J prend en charge plus de 90 langues et utilise des traductions basées sur le référentiel CLDR (une norme de l'industrie).
la source
Une version Java 8 basée sur la réponse de user678573 :
... car il n'y a pas de PeriodFormatter dans Java 8 et aucune méthode comme getHours, getMinutes, ...
Je serais heureux de voir une meilleure version pour Java 8.
la source
Je me rends compte que cela peut ne pas correspondre exactement à votre cas d'utilisation, mais PrettyTime peut être utile ici.
la source