Je voudrais formater une durée en secondes en utilisant un modèle comme H: MM: SS. Les utilitaires actuels en Java sont conçus pour formater une heure mais pas une durée.
Si vous utilisez une version de Java antérieure à 8 ... vous pouvez utiliser Joda Time et PeriodFormatter
. Si vous avez vraiment une durée (c.-à-d. Une durée écoulée, sans référence à un système de calendrier), vous devriez probablement utiliser Duration
pour la plupart - vous pouvez alors appeler toPeriod
(en spécifiant le paramètre PeriodType
que vous souhaitez indiquer si 25 heures deviennent 1 jour et 1 heure ou non, etc.) pour obtenir un Period
que vous pouvez formater.
Si vous utilisez Java 8 ou une version ultérieure: normalement, je suggérerais d'utiliser Java.time.Duration
pour représenter la durée. Vous pouvez ensuite appeler getSeconds()
ou similaire pour obtenir un entier pour le formatage de chaîne standard, conformément à la réponse de bobince si nécessaire - même si vous devez faire attention à la situation dans laquelle la durée est négative, car vous souhaitez probablement un single négatif connectez-vous à la chaîne de sortie. Donc, quelque chose comme:
public static String formatDuration(Duration duration) {
long seconds = duration.getSeconds();
long absSeconds = Math.abs(seconds);
String positive = String.format(
"%d:%02d:%02d",
absSeconds / 3600,
(absSeconds % 3600) / 60,
absSeconds % 60);
return seconds < 0 ? "-" + positive : positive;
}
Le formatage de cette manière est raisonnablement simple, si manuellement fastidieux. Pour parsing, cela devient en général plus difficile ... Vous pouvez toujours utiliser Joda Time, même avec Java 8, si vous le souhaitez, bien sûr.
Si vous ne voulez pas glisser dans les bibliothèques, il est assez simple d'utiliser un formateur ou un raccourci associé, par exemple. nombre entier de secondes donné s:
String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
J'utilise DurationFormatUtils commun d'Apache like so:
DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);
long duration = 4 * 60 * 60 * 1000;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
log.info("Duration: " + sdf.format(new Date(duration - TimeZone.getDefault().getRawOffset())));
Ce sera plus facile avec Java 9. Une Duration
n’est toujours pas formatable (ce que je sais), mais des méthodes permettant d’obtenir les heures, les minutes et les secondes sont ajoutées, ce qui simplifie un peu la tâche:
Duration diff = // ...;
String hms = String.format("%d:%02d:%02d",
diff.toHoursPart(),
diff.toMinutesPart(),
diff.toSecondsPart());
C'est peut-être un peu compliqué, mais c'est une bonne solution si vous voulez accomplir cela en utilisant le Java.time
de Java 8:
import Java.time.Duration;
import Java.time.LocalDateTime;
import Java.time.format.DateTimeFormatter;
import Java.time.format.DateTimeFormatterBuilder;
import Java.time.temporal.ChronoField;
import Java.time.temporal.Temporal;
import Java.time.temporal.TemporalAccessor;
import Java.time.temporal.TemporalField;
import Java.time.temporal.UnsupportedTemporalTypeException;
public class TemporalDuration implements TemporalAccessor {
private static final Temporal BASE_TEMPORAL = LocalDateTime.of(0, 1, 1, 0, 0);
private final Duration duration;
private final Temporal temporal;
public TemporalDuration(Duration duration) {
this.duration = duration;
this.temporal = duration.addTo(BASE_TEMPORAL);
}
@Override
public boolean isSupported(TemporalField field) {
if(!temporal.isSupported(field)) return false;
long value = temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
return value!=0L;
}
@Override
public long getLong(TemporalField field) {
if(!isSupported(field)) throw new UnsupportedTemporalTypeException(new StringBuilder().append(field.toString()).toString());
return temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
}
public Duration getDuration() {
return duration;
}
@Override
public String toString() {
return dtf.format(this);
}
private static final DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.optionalStart()//second
.optionalStart()//minute
.optionalStart()//hour
.optionalStart()//day
.optionalStart()//month
.optionalStart()//year
.appendValue(ChronoField.YEAR).appendLiteral(" Years ").optionalEnd()
.appendValue(ChronoField.MONTH_OF_YEAR).appendLiteral(" Months ").optionalEnd()
.appendValue(ChronoField.DAY_OF_MONTH).appendLiteral(" Days ").optionalEnd()
.appendValue(ChronoField.HOUR_OF_DAY).appendLiteral(" Hours ").optionalEnd()
.appendValue(ChronoField.MINUTE_OF_HOUR).appendLiteral(" Minutes ").optionalEnd()
.appendValue(ChronoField.SECOND_OF_MINUTE).appendLiteral(" Seconds").optionalEnd()
.toFormatter();
}
Cela va être l'une des nouvelles fonctionnalités de Java 7
Voici un autre exemple de mise en forme de la durée ..__ Notez que cet exemple montre à la fois la durée positive et la durée négative.
import static Java.time.temporal.ChronoUnit.DAYS;
import static Java.time.temporal.ChronoUnit.HOURS;
import static Java.time.temporal.ChronoUnit.MINUTES;
import static Java.time.temporal.ChronoUnit.SECONDS;
import Java.time.Duration;
public class DurationSample {
public static void main(String[] args) {
//Let's say duration of 2days 3hours 12minutes and 46seconds
Duration d = Duration.ZERO.plus(2, DAYS).plus(3, HOURS).plus(12, MINUTES).plus(46, SECONDS);
//in case of negative duration
if(d.isNegative()) d = d.negated();
//format DAYS HOURS MINUTES SECONDS
System.out.printf("Total duration is %sdays %shrs %smin %ssec.\n", d.toDays(), d.toHours() % 24, d.toMinutes() % 60, d.getSeconds() % 60);
//or format HOURS MINUTES SECONDS
System.out.printf("Or total duration is %shrs %smin %sec.\n", d.toHours(), d.toMinutes() % 60, d.getSeconds() % 60);
//or format MINUTES SECONDS
System.out.printf("Or total duration is %smin %ssec.\n", d.toMinutes(), d.getSeconds() % 60);
//or format SECONDS only
System.out.printf("Or total duration is %ssec.\n", d.getSeconds());
}
}
Ceci est une option de travail.
public static String showDuration(LocalTime otherTime){
DateTimeFormatter df = DateTimeFormatter.ISO_LOCAL_TIME;
LocalTime now = LocalTime.now();
System.out.println("now: " + now);
System.out.println("otherTime: " + otherTime);
System.out.println("otherTime: " + otherTime.format(df));
Duration span = Duration.between(otherTime, now);
LocalTime fTime = LocalTime.ofNanoOfDay(span.toNanos());
String output = fTime.format(df);
System.out.println(output);
return output;
}
Appelez la méthode avec
System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));
Produit quelque chose comme:
otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463
Que diriez-vous de la fonction suivante, qui renvoie soit + H: MM: SS
public static String formatInterval(final long interval, boolean millisecs )
{
final long hr = TimeUnit.MILLISECONDS.toHours(interval);
final long min = TimeUnit.MILLISECONDS.toMinutes(interval) %60;
final long sec = TimeUnit.MILLISECONDS.toSeconds(interval) %60;
final long ms = TimeUnit.MILLISECONDS.toMillis(interval) %1000;
if( millisecs ) {
return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
} else {
return String.format("%02d:%02d:%02d", hr, min, sec );
}
}
String duration(Temporal from, Temporal to) {
final StringBuilder builder = new StringBuilder();
for (ChronoUnit unit : new ChronoUnit[]{YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS}) {
long amount = unit.between(from, to);
if (amount == 0) {
continue;
}
builder.append(' ')
.append(amount)
.append(' ')
.append(unit.name().toLowerCase());
from = from.plus(amount, unit);
}
return builder.toString().trim();
}
Cette réponse utilise uniquement les méthodes Duration
et fonctionne avec Java 8:
public static String format(Duration d) {
long days = d.toDays();
d = d.minusDays(days);
long hours = d.toHours();
d = d.minusHours(hours);
long minutes = d.toMinutes();
d = d.minusMinutes(minutes);
long seconds = d.getSeconds() ;
return
(days == 0?"":days+" jours,")+
(hours == 0?"":hours+" heures,")+
(minutes == 0?"":minutes+" minutes,")+
(seconds == 0?"":seconds+" secondes,");
}
Ma bibliothèque Time4J offre une solution basée sur un modèle (similaire à Apache DurationFormatUtils
, mais plus flexible):
Duration<ClockUnit> duration =
Duration.of(-573421, ClockUnit.SECONDS) // input in seconds only
.with(Duration.STD_CLOCK_PERIOD); // performs normalization to h:mm:ss-structure
String fs = Duration.formatter(ClockUnit.class, "+##h:mm:ss").format(duration);
System.out.println(fs); // output => -159:17:01
Ce code illustre les fonctionnalités permettant de gérer le débordement d'heures et la gestion des signatures. Voir également l'API de duration-formatter basée sur le modèle .
en scala, pas de bibliothèque nécessaire:
def prettyDuration(str:List[String],seconds:Long):List[String]={
seconds match {
case t if t < 60 => str:::List(s"${t} seconds")
case t if (t >= 60 && t< 3600 ) => List(s"${t / 60} minutes"):::prettyDuration(str, t%60)
case t if (t >= 3600 && t< 3600*24 ) => List(s"${t / 3600} hours"):::prettyDuration(str, t%3600)
case t if (t>= 3600*24 ) => List(s"${t / (3600*24)} days"):::prettyDuration(str, t%(3600*24))
}
}
val dur = prettyDuration(List.empty[String], 12345).mkString("")
Dans Scala, construire sur la solution de YourBestBet mais simplifié:
def prettyDuration(seconds: Long): List[String] = seconds match {
case t if t < 60 => List(s"${t} seconds")
case t if t < 3600 => s"${t / 60} minutes" :: prettyDuration(t % 60)
case t if t < 3600*24 => s"${t / 3600} hours" :: prettyDuration(t % 3600)
case t => s"${t / (3600*24)} days" :: prettyDuration(t % (3600*24))
}
val dur = prettyDuration(12345).mkString(", ") // => 3 hours, 25 minutes, 45 seconds