Wie berechnet man mit Joda-Time die verstrichene Zeit?


70

Ich muss die Zeit berechnen, die von einem bestimmten Datum bis jetzt vergangen ist, und sie mit demselben Format wie StackOverflow-Fragen anzeigen, dh:

15s ago
2min ago
2hours ago
2days ago
25th Dec 08

Wissen Sie, wie Sie dies mit der Java Joda-Time- Bibliothek erreichen können ? Gibt es eine Hilfsmethode, die sie bereits implementiert, oder sollte ich den Algorithmus selbst schreiben?


3
"25th Dec 08" ist keine "Zeit, die von einem bestimmten Datum bis jetzt vergangen ist" (die Sie fett geschrieben haben;)
SyntaxT3rr0r

Ich weiß. Aber SO zeigt die Zeit, in der Fragen gestellt werden, so an. Wenn der Zeitraum lang genug ist, wird das genaue Datum angezeigt.
fabien7474

1
Ich bin ziemlich unzufrieden mit den StackOverflow-Bearbeitungsdaten. Sie erhalten zunächst sehr genaue Zahlen (vor 37 Sekunden), diese werden jedoch bald sehr vage (vor 2 Tagen). Erst nachdem die Uhrzeit im absoluten Format angezeigt wurde, können Sie das genaue Datum (und die Minuten) wieder anzeigen. Ich glaube, dass diese Art von relativen Informationen nur zusätzlich zu den absoluten nützlich ist, sie aber nicht ersetzen kann.
Svante

5
Die genaue Datums- und Uhrzeitangabe erhalten Sie im Tooltip. Bewegen Sie einfach die Datumszeit ein wenig :)
BalusC

Joda-Time eignet sich nicht zum Drucken der relativen (verstrichenen) Zeit, wenn Sie zusätzliche Funktionen benötigen. Die akzeptierte Antwort ist in Ordnung, aber nicht lokalisierbar (nur für Englisch). Wenn Sie Lokalisierungsunterstützung benötigen, gibt es bessere Bibliotheken von Drittanbietern. ocpsoft / PrettyTime ist eine bessere Option, funktioniert aber java.util.Datenur mit der alten Klasse . Meine Bibliothek Time4J ist jedoch meiner Meinung nach die beste Bibliothek zum Drucken von relativen Zeiten (Vor-Format) oder Zeiten im Format "3 Monate, 4 Tage". Es ist auch für tatsächlich 72 Sprachen lokalisierbar.
Meno Hochschild

Antworten:


113

Verwenden Sie, um die verstrichene Zeit mit JodaTime zu berechnen Period. Verwenden PeriodFormatterSie diese Option, um die verstrichene Zeit in der gewünschten menschlichen Darstellung zu formatierenPeriodFormatterBuilder .

Hier ist ein Kickoff-Beispiel:

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()
    .appendSeconds().appendSuffix(" seconds ago\n")
    .appendMinutes().appendSuffix(" minutes ago\n")
    .appendHours().appendSuffix(" hours ago\n")
    .appendDays().appendSuffix(" days ago\n")
    .appendWeeks().appendSuffix(" weeks ago\n")
    .appendMonths().appendSuffix(" months ago\n")
    .appendYears().appendSuffix(" years ago\n")
    .printZeroNever()
    .toFormatter();

String elapsed = formatter.print(period);
System.out.println(elapsed);

Dies wird jetzt gedruckt

Vor 3 Sekunden
Vor 51 Minuten
vor 7 Stunden
Vor 6 Tagen
vor 10 Monaten
Vor 31 Jahren

(Husten, alt, Husten) Sie sehen, dass ich auch Monate und Jahre berücksichtigt und so konfiguriert habe, dass die Werte weggelassen werden, wenn diese Null sind.


2
Danke. Ich habe Ihren Code als Grundlage für meinen Algorithmus verwendet. Grundsätzlich zeige ich die verstrichene Zeit mit 1 Feld an (oder nur maximal 2). Wenn sich jemand für den Code interessiert, kann ich ihn hier als Antwort posten. Es ist auch i18-konform.
fabien7474

1
Ich habe mit dem obigen Code getestet und festgestellt, dass dem Formatierer das Wochenfeld fehlt - die Tage werden nach Tag 6 umbrochen. Also habe ich hinzugefügt: .appendWeeks (). AppendSuffix ("vor Wochen \ n")
Mike Hopper

5
@ fabien7474 Wie haben Sie es angepasst, um nur ein Feld anzuzeigen? Bitte poste es als Antwort.
Karl

2
@ fabien7474 wirklich, wie hast du es angepasst, um nur ein Feld anzuzeigen?
OKO

1
Überprüfen Sie diese Liste, um nur ein Feld anzuzeigen .
Laranjeiro

20

Verwenden Sie PrettyTime für die einfache verstrichene Zeit.

Ich habe HumanTime ausprobiert als @sfussenegger beantwortet und mit JodaTime ist Periodaber die einfachste und sauberste Methode für die Menschen lesbare verstrichene Zeit , dass ich fand das war PrettyTime Bibliothek.

Hier einige einfache Beispiele mit Ein- und Ausgabe:

Vor fünf Minuten

DateTime fiveMinutesAgo = DateTime.now().minusMinutes( 5 );

new PrettyTime().format( fiveMinutesAgo.toDate() );

// Outputs: "5 minutes ago"

Vor einiger Zeit

DateTime birthday = new DateTime(1978, 3, 26, 12, 35, 0, 0);

new PrettyTime().format( birthday.toDate() );

// Outputs: "4 decades ago"

VORSICHT: Ich habe versucht, mit der präziseren Funktionalität der Bibliothek herumzuspielen, aber sie führt zu merkwürdigen Ergebnissen. Verwenden Sie sie daher vorsichtig und in nicht lebensbedrohlichen Projekten.

JP


11

Sie können dies mit einem PeriodFormatter tun, müssen sich jedoch nicht wie in anderen Antworten die Mühe machen, Ihren eigenen PeriodFormatBuilder zu erstellen . Wenn es zu Ihrem Fall passt, können Sie einfach den Standardformatierer verwenden:

Period period = new Period(startDate, endDate);
System.out.println(PeriodFormat.getDefault().print(period))

(Hut Tipp zu dieser Antwort auf eine ähnliche Frage, ich bin Cross-Posting für Auffindbarkeit)


Ich habe es gerade versucht und es gibt eine Aufschlüsselung des Zeitraums durch alle Felder in Millisekunden, daher ist getDefault () nicht so hilfreich.
NealeU

1
Ich das gerade versucht , und es gibt eine Aufschlüsselung der Zeit durch alle Felder Millisekunden, so getDefault () ist hilfreich. (Danke @snappieT)
Synesso

Dies ist kurz und ausreichend für die meisten Anwendungsfälle.
James Selvakumar

8

Es gibt eine kleine Helferklasse namens HumanTime , mit der ich ziemlich zufrieden bin.


1
Das ist toll. Das Hinzufügen eines einfachen Beispiels für Eingabe und Ausgabe zu Ihrer Antwort wäre sehr hilfreich.
Joshua Pinter

0

Hierbei wird der MySQL-Zeitstempel verwendet, um die bisher verstrichene Zeit abzurufen. Singular und Plular wird verwaltet. Nur die maximale Zeit anzeigen.

HINWEIS: Stellen Sie Ihre eigene Zeitzone ein.

String getElapsedTime(String strMysqlTimestamp) {
    
    DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss.S");
    DateTime mysqlDate = formatter.parseDateTime(strMysqlTimestamp).
                         withZone(DateTimeZone.forID("Asia/Kuala_Lumpur"));
    
    DateTime now = new DateTime();
    Period period = new Period(mysqlDate, now);
    
    int seconds = period.getSeconds();
    int minutes = period.getMinutes();
    int hours = period.getHours();
    int days = period.getDays();
    int weeks = period.getWeeks();
    int months = period.getMonths();
    int years = period.getYears();
    
    String elapsedTime = "";
    if (years != 0)
        if (years == 1)
            elapsedTime = years + " year ago";
        else
            elapsedTime = years + " years ago";
    else if (months != 0)
        if (months == 1)
            elapsedTime = months + " month ago";
        else
            elapsedTime = months + " months ago";
    else if (weeks != 0)
        if (weeks == 1)
            elapsedTime = weeks + " week ago";
        else
            elapsedTime = weeks + " weeks ago";
    else if (days != 0)
        if (days == 1)
            elapsedTime = days + " day ago";
        else
            elapsedTime = days + " days ago";
    else if (hours != 0)
        if (hours == 1)
            elapsedTime = hours + " hour ago";
        else
            elapsedTime = hours + " hours ago";
    else if (minutes != 0)
        if (minutes == 1)
            elapsedTime = minutes + " minute ago";
        else
            elapsedTime = minutes + " minutes ago";
    else if (seconds != 0)
        if (seconds == 1)
            elapsedTime = seconds + " second ago";
        else
            elapsedTime = seconds + " seconds ago";   
    
    return elapsedTime;
} 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.