Yanıtlar:
8'den önce bir Java sürümü kullanıyorsanız ... Joda Time ve PeriodFormatter
. Gerçekten bir süreniz varsa (yani, bir takvim sistemine referans olmadan geçen bir süre), muhtemelen Duration
çoğunlukla kullanmalısınız - daha sonra arayabilirsiniz toPeriod
( PeriodType
25 saatin gerçekleşip gerçekleşmeyeceğini yansıtmak istediğiniz her şeyi belirterek) 1 gün 1 saat ya da değil, vb.)Period
Biçimlendirebileceğiniz bir.
Java 8 veya daha yenisini kullanıyorsanız: Normalde java.time.Duration
süreyi göstermek için kullanılmasını öneririm . Daha sonra getSeconds()
gerekiyorsa, bobince'nin cevabına göre standart dize biçimlendirmesi için bir tam sayı elde etmek için arayabilir veya benzer bir şey yapabilirsiniz - yine de, çıkış dizesinde tek bir negatif işaret istediğinizden, sürenin negatif olduğu duruma dikkat etmelisiniz. . Yani şöyle bir şey:
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;
}
Bu şekilde biçimlendirme , rahatsız edici bir şekilde manuel ise oldukça basittir. İçin ayrıştırma elbette, isterseniz o daha sert madde genel olarak olur ... Hala bile Java 8 ile Joda Zaman kullanabilirsiniz.
Duration
ler yöntemleri: duration.toHours()
, duration.toMinutesPart()
ve duration.toSecondsPart()
Java 9. beri hangi Ve mutlak değer birini kullanabilirsiniz almak için duration.abs()
.
Kitaplıklarda sürüklemek istemiyorsanız, bir Biçimlendirici veya ilgili bir kısayol kullanarak kendinizi kolayca yapabilirsiniz. saniye cinsinden tamsayı s:
String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
s/86400, (s%86400)/3600...
gerekirse günlerce ayırabilirsiniz ...
s > 8640
0 (bir gün) için çözümüm : "\u221E"
- sonsuzluk
Apache common's DurationFormatUtils şöyle kullanıyorum :
DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);
Java 9'dan beri bu daha kolaydır. A Duration
hala biçimlendirilemez, ancak saati, dakikayı ve saniyeleri elde etmek için yöntemler eklenir, bu da görevi biraz daha basit hale getirir:
LocalDateTime start = LocalDateTime.of(2019, Month.JANUARY, 17, 15, 24, 12);
LocalDateTime end = LocalDateTime.of(2019, Month.JANUARY, 18, 15, 43, 33);
Duration diff = Duration.between(start, end);
String hms = String.format("%d:%02d:%02d",
diff.toHours(),
diff.toMinutesPart(),
diff.toSecondsPart());
System.out.println(hms);
Bu snippet'in çıktısı:
24:19:21
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())));
sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));
kullanmadan önce eklemeniz gerekir format
.
Bu biraz kibirli olabilir, ancak Java 8'leri kullanarak bunu başarmak için bükülmüşse iyi bir çözümdür java.time
:
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();
}
Duration.ofSeconds(20)
), sonra bir alırdım UnsupportedTemporalTypeException
). Ben sadece fark olup olmadığını kontrol kod kaldırdım == 01
. 01
Tam olarak anlamadığım bir çeşit maskeleme değeri olduğunu düşündüm , açıklayabilir misiniz?
isSupported
Yönteme gelince , insan tarafından okunabilir dizede gösterilecek geçerli bir alan varsa bilgileri döndürmesi. Her neyse, "maskeleme" aslında bir maske değildir. Kod gösterileri return value!=0l
değil return value!=01
. Lütfen bir dahaki sefere kopyala-yapıştır yöntemini kullanın.
TemporalAccessor
süreler boyunca yanlış kullanılması gerekmez. JSR-310 TemporalAmount
bu amaç için arayüzü tasarlamıştır .
L
Bir long
değeri belirtmek için her zaman büyük harf kullanmanızı öneririz . Daha l
önce gösterildiği gibi, basamak 1 için küçük harfleri yanlış okumak çok kolaydır .
Burada sürenin nasıl biçimlendirileceği ile ilgili bir örnek daha verilmiştir. Bu örneğin hem pozitif hem de negatif süreyi pozitif süre olarak gösterdiğine dikkat edin.
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());
}
}
Bu yanıt yalnızca Duration
yöntemleri kullanır ve Java 8 ile çalışır:
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,");
}
Bu, çalışan bir seçenektir.
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;
}
Yöntemi şununla çağırın:
System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));
Şuna benzer bir şey üretir:
otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463
+ H: MM: SS veya + H: MM: SS.sss döndüren aşağıdaki işleve ne dersiniz?
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 );
}
}
En azından 24 saatten daha kısa süreler için oldukça basit ve (IMO) zarif bir yaklaşım var:
DateTimeFormatter.ISO_LOCAL_TIME.format(value.addTo(LocalTime.of(0, 0)))
Biçimlendiricilerin biçimlendirmek için geçici bir nesneye ihtiyacı vardır, böylece LocalTime'a 00:00 (yani gece yarısı) süresini ekleyerek bir nesne oluşturabilirsiniz. Bu, gece yarısından o zamana kadar olan süreyi temsil eden ve daha sonra standart SS: dd: sn gösterimlerinde biçimlendirmek için kolay olan bir LocalTime verecektir. Bu, harici bir kütüphaneye ihtiyaç duymama avantajına sahiptir ve hesaplama için saatleri, dakikaları ve saniyeleri manuel olarak hesaplamak yerine java.time kütüphanesini kullanır.
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();
}
bu fontu kullanarak
private static String strDuration(long duration) {
int ms, s, m, h, d;
double dec;
double time = duration * 1.0;
time = (time / 1000.0);
dec = time % 1;
time = time - dec;
ms = (int)(dec * 1000);
time = (time / 60.0);
dec = time % 1;
time = time - dec;
s = (int)(dec * 60);
time = (time / 60.0);
dec = time % 1;
time = time - dec;
m = (int)(dec * 60);
time = (time / 24.0);
dec = time % 1;
time = time - dec;
h = (int)(dec * 24);
d = (int)time;
return (String.format("%d d - %02d:%02d:%02d.%03d", d, h, m, s, ms));
}
Kütüphanem Time4J , desen tabanlı bir çözüm sunuyor (buna benzer Apache DurationFormatUtils
ancak daha esnek):
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
Bu kod, saat taşması ve işaret işlemeyi işleme yeteneklerini gösterir, ayrıca kalıba dayalı süre biçimlendiricisinin API'sına bakın .
Skala'da (başka denemeler gördüm ve etkilenmedim):
def formatDuration(duration: Duration): String = {
import duration._ // get access to all the members ;)
f"$toDaysPart $toHoursPart%02d:$toMinutesPart%02d:$toSecondsPart%02d:$toMillisPart%03d"
}
Korkunç görünüyor evet? İşte bu yüzden metodu çağırmak için IDE'leri kullanıyoruz.$toHoursPart
vb.) Farklı bir renk .
f"..."
Bir olan printf
/ String.format
(mümkün kılan budur tarzı dize interpolator $
bir çıkış Verilen işe yerleştirilen kodu) 1 14:06:32.583
, f
ara değerli dize eşdeğer olacaktırString.format("1 %02d:%02d:%02d.%03d", 14, 6, 32, 583)
Scala'da YourBestBet'in çözümünü temel alıyor ancak basitleştirilmiş:
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
scala'da kütüphane gerekmez:
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("")
Bunu görmedim, bu yüzden ekleyeceğimi düşündüm:
Date started=new Date();
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
task
long duration=new Date().getTime()-started.getTime();
System.out.println(format.format(new Date(duration));
Sadece 24 saat çalışıyor ama genelde bu süreyi istiyorum.