Chcę zarejestrować czas, w System.currentTimeMillis()
którym użytkownik zaczyna coś w moim programie. Kiedy skończy, odejmę prąd System.currentTimeMillis()
od start
zmiennej i chcę pokazać im upływ czasu, używając czytelnego dla człowieka formatu, takiego jak „XX godzin, XX minut, XX sekund” lub nawet „XX minut, XX sekund”, ponieważ jego raczej nie zajmie to komuś godziny.
Jak najlepiej to zrobić?
Odpowiedzi:
Użyj
java.util.concurrent.TimeUnit
klasy:Uwaga:
TimeUnit
jest częścią specyfikacji Java 1.5, aletoMinutes
została dodana od wersji Java 1.6.Aby dodać wiodące zero dla wartości 0–9, po prostu wykonaj:
Jeśli
TimeUnit
lubtoMinutes
nie są obsługiwane (np. W systemie Android przed wersją API 9), użyj następujących równań:źródło
int hours = (int) ((milliseconds / (1000*60*60)) % 24)
to nie działa! zamiast tego powinno być takint hours = (int) (milliseconds / (1000*60*60)) ;
String.format("%01d:%02d:%02d", hours, minutes, seconds);
Na podstawie odpowiedzi @ siddhadev napisałem funkcję, która konwertuje milisekundy na sformatowany ciąg:
źródło
1 Days 1 Hours 1 Minutes 1 Seconds
long days = TimeUnit.MILLISECONDS.toDays(millis);
long hours = TimeUnit.MILLISECONDS.toHours(millis) % 24;
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60;
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;
long milliseconds = millis % 1000;
a także metody String.format:return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds", days, hours, minutes, seconds, milliseconds);
Wydruki:
źródło
Duration dur = new Duration(start, end);
long millis = dur.getMillis();
DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time));
lub zmień Czas trwania na okres, który można automatycznie wydrukować za pomocą JodyPeriodFormatter
. Konwersja może mieć utratę precyzji, jeśli jest inna niż chronologia ISO. Załóżmy czas trwania reprezentowany przez zmiennąduration
.Period period = duration.toPeriod().normalizedStandard(PeriodType.time());
PeriodFormat.getDefault().print(period))
Wydajność jest niesamowita: 1 sekunda i 581 milisekund, odpowiadając na główne pytanie powyżej.Uhm ... ile milisekund trwa sekunda? A za minutę? Podział nie jest taki trudny.
Kontynuuj tak przez godziny, dni, tygodnie, miesiące, rok, dekady, cokolwiek.
źródło
Korzystanie z pakietu java.time w Javie 8:
Dane wyjściowe są w formacie czasu trwania ISO 8601 :
PT1M3.553S
(1 minuta i 3,553 sekundy).źródło
Nie wciągałbym w to dodatkowej zależności (przecież podział nie jest wcale taki trudny), ale jeśli mimo wszystko używasz Commons Lang, istnieją DurationFormatUtils .
Przykładowe użycie (dostosowane tutaj ):
Przykład:
Uwaga : Aby uzyskać millis z dwóch obiektów LocalDateTime, możesz użyć:
źródło
Wybierz podział ręki lub użyj interfejsu API SimpleDateFormat .
Edytuj przez Bombe : W komentarzach wykazano, że to podejście działa tylko przez krótsze okresy (tj. Krócej niż jeden dzień).
źródło
Aby dodać więcej informacji, jeśli chcesz sformatować: HH: mm: ss
0 <= HH <= nieskończony
0 <= mm <60
0 <= ss <60
Użyj tego:
Właśnie miałem ten problem i wymyśliłem to
źródło
Myślę, że najlepszym sposobem jest:
źródło
Najkrótsze rozwiązanie:
Oto prawdopodobnie najkrótszy, który dotyczy również stref czasowych.
Które wyjścia na przykład:
Wyjaśnienie:
%tT
to czas sformatowany dla zegara 24-godzinnego jako%tH:%tM:%tS
.%tT
akceptuje również longs jako dane wejściowe, więc nie ma potrzeby tworzeniaDate
.printf()
wypisze po prostu czas określony w milisekundach, ale w bieżącej strefie czasowej, dlatego musimy odjąć surowe przesunięcie bieżącej strefy czasowej, aby 0 milisekund wynosiło 0 godzin, a nie wartość przesunięcia czasowego bieżącej strefy czasowej.Uwaga 1: Jeśli potrzebujesz wyniku jako
String
, możesz uzyskać go w następujący sposób:Uwaga 2: Daje to poprawny wynik tylko, jeśli
millis
jest krótszy niż jeden dzień, ponieważ część dzienna nie jest uwzględniona w danych wyjściowych.źródło
long millis = 8398;
a kiedyString.format("%tT", millis)
przekażę to do mojego wyjścia jest 19:00:08. Skąd pochodzi 19?TimeZone.getDefault().getRawOffset()
, dokładnie tak, jak napisano w odpowiedzi:String.format("%tT", millis-TimeZone.getDefault().getRawOffset())
Joda-Time
Korzystanie z Joda-Time :
źródło
PeriodFormat
w ostatnim wierszu. Po prostu zadzwoń,Period::toString
aby uzyskać domyślnie ciąg czasu trwania ISO 8601 .Przeglądając wkład @ brent-nash, moglibyśmy użyć funkcji modułu zamiast odejmowania i użyć metody String.format dla ciągu wynikowego:
źródło
dla Androida poniżej API 9
źródło
Na małe czasy, mniej niż godzinę, wolę:
dla dłuższych interwałów:
źródło
%tH
tylko od 0 do 23 godzin? Oznacza to, że na przykład 24 godziny będą wyświetlane jako00
, 25 godzin jako01
... tak samo ważne przez%tT
- dni zostaną po cichu odrzucone. Jasne, może również wyświetlać dni, ale byłoby to przesadą w stosunku do problemu, który miałem, kiedy to napisałem (w 2011 roku) [:-)Moje proste obliczenia:
Miłego kodowania :)
źródło
Oto odpowiedź oparta na odpowiedzi Brenta Nasha, Mam nadzieję, że to pomaga!
źródło
źródło
diff=diff-(hours*60*1000);
powinno byćdiff=diff-(hours*60*60*1000);
. Próbowałem go edytować, ale irytująca polityka edycji StackOverflow mówi, że nie ma wystarczającej liczby znaków do edycji.Po pierwsze,
System.currentTimeMillis()
iInstant.now()
nie są idealne do pomiaru czasu. Obaj zgłaszają czas naścienny, którego komputer nie zna dokładnie i który może poruszać się nieregularnie, w tym cofać się, jeśli na przykład demon NTP skoryguje czas systemowy. Jeśli twój pomiar czasu odbywa się na jednym komputerze, powinieneś zamiast tego użyć System.nanoTime () .Po drugie, począwszy od Java 8, java.time.Duration jest najlepszym sposobem na przedstawienie czasu trwania:
źródło
Jeśli wiesz, że różnica czasu byłaby mniejsza niż godzina, możesz użyć następującego kodu:
Wynik: 51:00
źródło
Ta odpowiedź jest podobna do niektórych odpowiedzi powyżej. Uważam jednak, że byłoby to korzystne, ponieważ w przeciwieństwie do innych odpowiedzi, usunie to dodatkowe przecinki lub białe znaki i będzie obsługiwać skrót.
źródło
Tam jest problem. Gdy milisekundy wynoszą 59999, w rzeczywistości jest to 1 minuta, ale zostanie obliczona jako 59 sekund, a 999 milisekund zostanie utraconych.
Oto zmodyfikowana wersja oparta na poprzednich odpowiedziach, która może rozwiązać tę stratę:
źródło
W Javie 9 jest to łatwiejsze:
To daje ciąg podobny do
0 hours, 39 mins, 9 seconds
.Jeśli chcesz zaokrąglić całe sekundy przed formatowaniem:
Aby pominąć godziny, jeśli wynoszą 0:
Teraz możemy mieć na przykład
39 mins, 9 seconds
.Aby wydrukować minuty i sekundy z wiodącym zerem, tak aby zawsze były dwiema cyframi, po prostu wstaw
02
do odpowiednich specyfikatorów formatu, a zatem:Teraz możemy mieć na przykład
0 hours, 39 mins, 09 seconds
.źródło
if
-else
tam.dla poprawnych ciągów („1 godzina, 3 sekundy”, „3 minuty”, ale nie „0 godzin, 0 minut, 3 sekundy”) piszę ten kod:
źródło
Zmodyfikowałem odpowiedź @MyKuLLSKI i dodałem obsługę plurlizacji. Wyjąłem sekundy, ponieważ nie potrzebowałem ich, ale możesz je dodać ponownie, jeśli potrzebujesz.
źródło
int intervalMins
vslong millis
Omówiłem to w innej odpowiedzi, ale możesz zrobić:
Wyjście jest coś w rodzaju
Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
z zamówionymi jednostkami.Od Ciebie zależy, jak internacjonalizować te dane zgodnie z docelowymi ustawieniami regionalnymi.
źródło
Użyj java.util.concurrent.TimeUnit i użyj tej prostej metody:
Na przykład:
źródło
DurationFormatUtils.formatDurationHMS (długi)
źródło