Jak obliczyć „czas temu” w Javie?


127

W Ruby on Rails jest funkcja, która umożliwia pobranie dowolnej daty i wydrukowanie „dawno temu”.

Na przykład:

8 minutes ago
8 hours ago
8 days ago
8 months ago
8 years ago

Czy istnieje łatwy sposób na zrobienie tego w Javie?


1
Zobacz: stackoverflow.com/questions/11/how-do-i-calculate-relative-time To jest C #, ale jestem pewien, że możesz go przekonwertować z niewielkim problemem.
Brandon

Odpowiedzi:


177

Spójrz na bibliotekę PrettyTime .

Jest dość prosty w użyciu:

import org.ocpsoft.prettytime.PrettyTime;

PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
// prints "moments ago"

Możesz również podać ustawienia regionalne dla wiadomości międzynarodowych:

PrettyTime p = new PrettyTime(new Locale("fr"));
System.out.println(p.format(new Date()));
// prints "à l'instant"

Jak zauważono w komentarzach, Android ma tę funkcję wbudowaną w android.text.format.DateUtilsklasę.


229
Jeśli pracujesz na Androidzie, możesz użyć tego: android.text.format.DateUtils # getRelativeTimeSpanString ()
Somatik

Czy możesz dodać więcej opisu do swojej odpowiedzi, odpowiedź z samym łączem nie jest na razie dobra.
Ajay S

@Somatik, jeśli chcesz to uzyskać na platformie innej niż Android, możesz wyświetlić tę klasę na AOSP.
greg7gkb

@ataylor, jak to używać w systemie Android?
Hardik Parmar

Funkcja getRelativeTimeSpanString nie jest idealna dla wszystkich sytuacji i dlatego stworzyłem własną klasę na podstawie wielu przykładów tutaj. Zobacz moje rozwiązanie poniżej: stackoverflow.com/a/37042254/468360
Codeversed

67

Czy rozważałeś wyliczenie TimeUnit ? Może to być całkiem przydatne do tego rodzaju rzeczy

    try {
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        Date past = format.parse("01/10/2010");
        Date now = new Date();

        System.out.println(TimeUnit.MILLISECONDS.toMillis(now.getTime() - past.getTime()) + " milliseconds ago");
        System.out.println(TimeUnit.MILLISECONDS.toMinutes(now.getTime() - past.getTime()) + " minutes ago");
        System.out.println(TimeUnit.MILLISECONDS.toHours(now.getTime() - past.getTime()) + " hours ago");
        System.out.println(TimeUnit.MILLISECONDS.toDays(now.getTime() - past.getTime()) + " days ago");
    }
    catch (Exception j){
        j.printStackTrace();
    }

4
Nie sądzę, że jest to pełna odpowiedź, ponieważ jednostki czasu są niezależne. Np. - czas milisekund to tylko minuty czas * 60 * 1000. Musisz zmniejszyć z każdej jednostki czasu kolejną większą jednostkę czasu (po przeliczeniu na niższą jednostkę czasu), aby móc z niej korzystać w "czasie temu " strunowy.
Nativ

@Benj - Czy to dobrze? powyższe rozwiązanie? ponieważ jeden czas jest w formacie 12-godzinnym, a inny w formacie 24-godzinnym. Daj mi znać swoją opinię dotyczącą mojego zapytania. Z góry dziękuję.
Swift

jest to jednak niepoprawne ... każda jednostka jest od siebie niezależna, jak już wspomniano.
Jonathan Laliberte

1
android robi to za ciebie Jeśli pracujesz na Androidzie, możesz użyć tego: android.text.format.DateUtils.getRelativeTimeSpanString (milisekundy)
Wajid Ali

50

Biorę odpowiedzi RealHowTo i Ben J i tworzę własną wersję:

public class TimeAgo {
public static final List<Long> times = Arrays.asList(
        TimeUnit.DAYS.toMillis(365),
        TimeUnit.DAYS.toMillis(30),
        TimeUnit.DAYS.toMillis(1),
        TimeUnit.HOURS.toMillis(1),
        TimeUnit.MINUTES.toMillis(1),
        TimeUnit.SECONDS.toMillis(1) );
public static final List<String> timesString = Arrays.asList("year","month","day","hour","minute","second");

public static String toDuration(long duration) {

    StringBuffer res = new StringBuffer();
    for(int i=0;i< TimeAgo.times.size(); i++) {
        Long current = TimeAgo.times.get(i);
        long temp = duration/current;
        if(temp>0) {
            res.append(temp).append(" ").append( TimeAgo.timesString.get(i) ).append(temp != 1 ? "s" : "").append(" ago");
            break;
        }
    }
    if("".equals(res.toString()))
        return "0 seconds ago";
    else
        return res.toString();
}
public static void main(String args[]) {
    System.out.println(toDuration(123));
    System.out.println(toDuration(1230));
    System.out.println(toDuration(12300));
    System.out.println(toDuration(123000));
    System.out.println(toDuration(1230000));
    System.out.println(toDuration(12300000));
    System.out.println(toDuration(123000000));
    System.out.println(toDuration(1230000000));
    System.out.println(toDuration(12300000000L));
    System.out.println(toDuration(123000000000L));
}}

co spowoduje wydrukowanie następującego

0 second ago
1 second ago
12 seconds ago
2 minutes ago
20 minutes ago
3 hours ago
1 day ago
14 days ago
4 months ago
3 years ago

Bardzo fajny. I bardzo łatwo jest dodać inne jednostki czasu, takie jak tydzień (tygodnie)
Piotr

1
ten zasługuje na więcej głosów. Przede wszystkim nie potrzeba żadnej biblioteki. Nadal jest czysty, elegancki i łatwy do zmiany.
fangzhzh

mała literówka: w kodzie odwołujesz się do statycznych właściwości „List” zamiast „TimeAgo”. Lists.times.get (i) powinno być TimeAgo.get (i) ... i tak dalej
Diogo Gomes

2
Mała sugestia: użyj .append(temp != 1 ? "s" : "")zamiast .append(temp > 1 ? "s" : "")ponieważ 0 powinno również mieć ssufiks
berkus

1
@ShajeelAfzal tak, parametr czasu trwania jest w milisekundach, ale jest to różnica między czasami, a nie wartość bezwzględna. To, co otrzymujesz, to czas, który minął od 1 stycznia 1970 roku, kiedy zaczął się znacznik czasu uniksowego
Riccardo Casatta

42
  public class TimeUtils {

      public final static long ONE_SECOND = 1000;
      public final static long SECONDS = 60;

      public final static long ONE_MINUTE = ONE_SECOND * 60;
      public final static long MINUTES = 60;

      public final static long ONE_HOUR = ONE_MINUTE * 60;
      public final static long HOURS = 24;

      public final static long ONE_DAY = ONE_HOUR * 24;

      private TimeUtils() {
      }

      /**
       * converts time (in milliseconds) to human-readable format
       *  "<w> days, <x> hours, <y> minutes and (z) seconds"
       */
      public static String millisToLongDHMS(long duration) {
        StringBuffer res = new StringBuffer();
        long temp = 0;
        if (duration >= ONE_SECOND) {
          temp = duration / ONE_DAY;
          if (temp > 0) {
            duration -= temp * ONE_DAY;
            res.append(temp).append(" day").append(temp > 1 ? "s" : "")
               .append(duration >= ONE_MINUTE ? ", " : "");
          }

          temp = duration / ONE_HOUR;
          if (temp > 0) {
            duration -= temp * ONE_HOUR;
            res.append(temp).append(" hour").append(temp > 1 ? "s" : "")
               .append(duration >= ONE_MINUTE ? ", " : "");
          }

          temp = duration / ONE_MINUTE;
          if (temp > 0) {
            duration -= temp * ONE_MINUTE;
            res.append(temp).append(" minute").append(temp > 1 ? "s" : "");
          }

          if (!res.toString().equals("") && duration >= ONE_SECOND) {
            res.append(" and ");
          }

          temp = duration / ONE_SECOND;
          if (temp > 0) {
            res.append(temp).append(" second").append(temp > 1 ? "s" : "");
          }
          return res.toString();
        } else {
          return "0 second";
        }
      }


      public static void main(String args[]) {
        System.out.println(millisToLongDHMS(123));
        System.out.println(millisToLongDHMS((5 * ONE_SECOND) + 123));
        System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR));
        System.out.println(millisToLongDHMS(ONE_DAY + 2 * ONE_SECOND));
        System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR + (2 * ONE_MINUTE)));
        System.out.println(millisToLongDHMS((4 * ONE_DAY) + (3 * ONE_HOUR)
            + (2 * ONE_MINUTE) + ONE_SECOND));
        System.out.println(millisToLongDHMS((5 * ONE_DAY) + (4 * ONE_HOUR)
            + ONE_MINUTE + (23 * ONE_SECOND) + 123));
        System.out.println(millisToLongDHMS(42 * ONE_DAY));
        /*
          output :
                0 second
                5 seconds
                1 day, 1 hour
                1 day and 2 seconds
                1 day, 1 hour, 2 minutes
                4 days, 3 hours, 2 minutes and 1 second
                5 days, 4 hours, 1 minute and 23 seconds
                42 days
         */
    }
}

więcej @ Sformatuj czas trwania w milisekundach do formatu czytelnego dla człowieka


Skończyło się na poprawionej wersji tego. Wysłałem dla Ciebie moje poprawki.
David Blevins,

5
David Blevins, więcej przykładów na temat PrettyTime: stackoverflow.com/questions/3859288/ ... Duże -1 za ponowne wymyślenie koła i niezalecanie biblioteki innej firmy :-p
zakmck

9

Jest to oparte na odpowiedzi RealHowTo, więc jeśli Ci się spodoba, okaż mu też trochę miłości.

Ta oczyszczona wersja umożliwia określenie zakresu czasu, który może Cię zainteresować.

Trochę inaczej też traktuje część „i”. Często stwierdzam, że łącząc ciągi z separatorem, często łatwiej jest pominąć skomplikowaną logikę i po prostu usunąć ostatni separator, gdy skończysz.

import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

public class TimeUtils {

    /**
     * Converts time to a human readable format within the specified range
     *
     * @param duration the time in milliseconds to be converted
     * @param max      the highest time unit of interest
     * @param min      the lowest time unit of interest
     */
    public static String formatMillis(long duration, TimeUnit max, TimeUnit min) {
        StringBuilder res = new StringBuilder();

        TimeUnit current = max;

        while (duration > 0) {
            long temp = current.convert(duration, MILLISECONDS);

            if (temp > 0) {
                duration -= current.toMillis(temp);
                res.append(temp).append(" ").append(current.name().toLowerCase());
                if (temp < 2) res.deleteCharAt(res.length() - 1);
                res.append(", ");
            }

            if (current == min) break;

            current = TimeUnit.values()[current.ordinal() - 1];
        }

        // clean up our formatting....

        // we never got a hit, the time is lower than we care about
        if (res.lastIndexOf(", ") < 0) return "0 " + min.name().toLowerCase();

        // yank trailing  ", "
        res.deleteCharAt(res.length() - 2);

        //  convert last ", " to " and"
        int i = res.lastIndexOf(", ");
        if (i > 0) {
            res.deleteCharAt(i);
            res.insert(i, " and");
        }

        return res.toString();
    }
}

Mały kod, aby nadać mu wir:

import static java.util.concurrent.TimeUnit.*;

public class Main {

    public static void main(String args[]) {
        long[] durations = new long[]{
            123,
            SECONDS.toMillis(5) + 123,
            DAYS.toMillis(1) + HOURS.toMillis(1),
            DAYS.toMillis(1) + SECONDS.toMillis(2),
            DAYS.toMillis(1) + HOURS.toMillis(1) + MINUTES.toMillis(2),
            DAYS.toMillis(4) + HOURS.toMillis(3) + MINUTES.toMillis(2) + SECONDS.toMillis(1),
            DAYS.toMillis(5) + HOURS.toMillis(4) + MINUTES.toMillis(1) + SECONDS.toMillis(23) + 123,
            DAYS.toMillis(42)
        };

        for (long duration : durations) {
            System.out.println(TimeUtils.formatMillis(duration, DAYS, SECONDS));
        }

        System.out.println("\nAgain in only hours and minutes\n");

        for (long duration : durations) {
            System.out.println(TimeUtils.formatMillis(duration, HOURS, MINUTES));
        }
    }

}

Który wyświetli następujące informacje:

0 seconds
5 seconds 
1 day and 1 hour 
1 day and 2 seconds 
1 day, 1 hour and 2 minutes 
4 days, 3 hours, 2 minutes and 1 second 
5 days, 4 hours, 1 minute and 23 seconds 
42 days 

Again in only hours and minutes

0 minutes
0 minutes
25 hours 
24 hours 
25 hours and 2 minutes 
99 hours and 2 minutes 
124 hours and 1 minute 
1008 hours 

A na wypadek, gdyby ktoś kiedykolwiek tego potrzebował, oto klasa, która przekształci dowolny ciąg, taki jak powyższy, z powrotem na milisekundy . Jest to bardzo przydatne, ponieważ pozwala ludziom określać limity czasu różnych rzeczy w czytelnym tekście.


9

można to zrobić w prosty sposób:

powiedzmy, że chcesz ustawić godzinę 20 minut temu:

Long minutesAgo = new Long(20);
Date date = new Date();
Date dateIn_X_MinAgo = new Date (date.getTime() - minutesAgo*60*1000);

Otóż ​​to..


1
W większości przypadków potrzebujesz „inteligentnego” wyświetlacza, tj. zamiast 5125 minut temu, mówisz x dni temu.
PhiLho,

7

O rozwiązaniach wbudowanych :

Java nie ma żadnej wbudowanej obsługi formatowania czasów względnych, także Java-8 i jej nowy pakiet java.time. Jeśli potrzebujesz tylko angielskiego i niczego więcej, wtedy i tylko wtedy ręcznie wykonane rozwiązanie może być akceptowalne - zobacz odpowiedź @RealHowTo (chociaż ma tę silną wadę, że nie bierze pod uwagę strefy czasowej przy tłumaczeniu natychmiastowych delt na czas lokalny jednostki!). W każdym razie, jeśli chcesz uniknąć skomplikowanych obejść opracowanych w domu, zwłaszcza w przypadku innych języków, potrzebujesz biblioteki zewnętrznej.

W drugim przypadku polecam skorzystać z mojej biblioteki Time4J (lub Time4A na Androidzie). Oferuje największą elastyczność i najwięcej mocy i18n . Klasa net.time4j.PrettyTime ma printRelativeTime...(...)do tego siedem metod . Przykład użycia zegara testowego jako źródła czasu:

TimeSource<?> clock = () -> PlainTimestamp.of(2015, 8, 1, 10, 24, 5).atUTC();
Moment moment = PlainTimestamp.of(2015, 8, 1, 17, 0).atUTC(); // our input
String durationInDays =
  PrettyTime.of(Locale.GERMAN).withReferenceClock(clock).printRelative(
    moment,
    Timezone.of(EUROPE.BERLIN),
    TimeUnit.DAYS); // controlling the precision
System.out.println(durationInDays); // heute (german word for today)

Inny przykład użycia java.time.Instantjako dane wejściowe:

String relativeTime = 
  PrettyTime.of(Locale.ENGLISH)
    .printRelativeInStdTimezone(Moment.from(Instant.EPOCH));
System.out.println(relativeTime); // 45 years ago

Ta biblioteka obsługuje w swojej najnowszej wersji (v4.17) 80 języków, a także niektóre ustawienia regionalne (szczególnie dla hiszpańskiego, angielskiego, arabskiego, francuskiego). Dane i18n są głównie oparte na najnowszej wersji CLDR v29 . Inne ważne powody, dla których warto korzystać z tej biblioteki, to dobra obsługa reguł liczby mnogiej (które często różnią się od angielskich w innych lokalizacjach), skrócony styl formatu (na przykład: „1 sekunda temu”) oraz wyraźne sposoby uwzględniania stref czasowych . Time4J zdaje sobie nawet sprawę z tak egzotycznych szczegółów, jak sekundy przestępne w obliczeniach czasów względnych (nie jest to naprawdę ważne, ale tworzy komunikat dotyczący horyzontu oczekiwań). Zgodność z Java-8istnieje dzięki łatwo dostępnym metodom konwersji dla typów takich jak java.time.Instantlub java.time.Period.

Czy są jakieś wady? Tylko dwa.

  • Biblioteka nie jest mała (także ze względu na duże repozytorium danych i18n).
  • Interfejs API nie jest dobrze znany, więc wiedza społeczności i wsparcie nie są jeszcze dostępne, w przeciwnym razie dostarczona dokumentacja jest dość szczegółowa i wyczerpująca.

(Kompaktowe) alternatywy:

Jeśli szukasz mniejszego rozwiązania i nie potrzebujesz tak wielu funkcji i jesteś gotów tolerować możliwe problemy z jakością związane z i18n-data, to:

  • Polecam ocpsoft / PrettyTime (wsparcie dla 32 języków (w rzeczywistości wkrótce 34) nadaje się do pracy z? java.util.DateTylko - patrz odpowiedź @ataylor). Standard branżowy CLDR (z konsorcjum Unicode) z jego dużym doświadczeniem społecznym nie jest niestety bazą danych i18n, więc dalsze ulepszenia lub ulepszenia danych mogą zająć trochę czasu ...

  • Jeśli używasz Androida, to pomocnicza klasa android.text.format.DateUtils jest wąską wbudowaną alternatywą (zobacz inne komentarze i odpowiedzi tutaj, z tą wadą, że nie ma wsparcia przez lata i miesiące. I jestem pewien, że tylko bardzo niewielu ludzi lubi styl API tej klasy pomocniczej.

  • Jeśli jesteś fanem Joda-Time , możesz spojrzeć na jego klasę PeriodFormat (obsługa 14 języków w wersji 2.9.4, z drugiej strony: Joda-Time z pewnością też nie jest kompaktowy, więc wspominam o tym tutaj tylko dla kompletność). Ta biblioteka nie jest prawdziwą odpowiedzią, ponieważ względne czasy w ogóle nie są obsługiwane. Będziesz musiał przynajmniej dodać dosłowne „temu” (i ręcznie usunąć wszystkie dolne jednostki z wygenerowanych formatów list - niezręczne). W przeciwieństwie do Time4J lub Android-DateUtils, nie ma specjalnej obsługi skrótów ani automatycznego przełączania z czasów względnych na reprezentacje czasu bezwzględnego. Podobnie jak PrettyTime, jest całkowicie zależny od niepotwierdzonego wkładu prywatnych członków społeczności Java do swoich danych i18n.


5

Jeśli szukasz prostego „Dzisiaj”, „Wczoraj” lub „X dni temu”.

private String getDaysAgo(Date date){
    long days = (new Date().getTime() - date.getTime()) / 86400000;

    if(days == 0) return "Today";
    else if(days == 1) return "Yesterday";
    else return days + " days ago";
}

5

java.time

Korzystanie ze środowiska java.time wbudowanego w język Java 8 i nowsze.

LocalDateTime t1 = LocalDateTime.of(2015, 1, 1, 0, 0, 0);
LocalDateTime t2 = LocalDateTime.now();
Period period = Period.between(t1.toLocalDate(), t2.toLocalDate());
Duration duration = Duration.between(t1, t2);

System.out.println("First January 2015 is " + period.getYears() + " years ago");
System.out.println("First January 2015 is " + period.getMonths() + " months ago");
System.out.println("First January 2015 is " + period.getDays() + " days ago");
System.out.println("First January 2015 is " + duration.toHours() + " hours ago");
System.out.println("First January 2015 is " + duration.toMinutes() + " minutes ago");

1
Te Durationmetody raportują cały czas trwania jako całkowitą liczbę godzin i jako całkowitą liczbę minut. W Javie 8 klasa dziwnie nie miała żadnych metod, aby uzyskać każdą część godziny, minut i sekund. Java 9 przynosi tych metod to…Part.
Basil Bourque


4

Jeśli tworzysz aplikację na Androida, zapewnia ona klasę narzędziową DateUtils dla wszystkich takich wymagań. Przyjrzyj się metodzie narzędziowej DateUtils # getRelativeTimeSpanString () .

Z dokumentów dla

CharSequence getRelativeTimeSpanString (długi czas, długi czas, długi minResolution)

Zwraca ciąg znaków opisujący „czas” jako czas względem „teraz”. Przedziały czasowe w przeszłości mają format „42 minuty temu”. Przedziały czasowe w przyszłości mają format „Za 42 minuty”.

Będziesz przechodzi swój timestampjak czas i System.currentTimeMillis()jak teraz . minResolutionPozwala określić minimalny Okres zgłosić.

Na przykład czas sprzed 3 sekund zostanie zgłoszony jako „0 minut temu”, jeśli jest ustawiony na MINUTE_IN_MILLIS. Podaj jeden z 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS itd.


4

Możesz użyć tej funkcji do obliczenia czasu temu

 private String timeAgo(long time_ago) {
        long cur_time = (Calendar.getInstance().getTimeInMillis()) / 1000;
        long time_elapsed = cur_time - time_ago;
        long seconds = time_elapsed;
        int minutes = Math.round(time_elapsed / 60);
        int hours = Math.round(time_elapsed / 3600);
        int days = Math.round(time_elapsed / 86400);
        int weeks = Math.round(time_elapsed / 604800);
        int months = Math.round(time_elapsed / 2600640);
        int years = Math.round(time_elapsed / 31207680);

        // Seconds
        if (seconds <= 60) {
            return "just now";
        }
        //Minutes
        else if (minutes <= 60) {
            if (minutes == 1) {
                return "one minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else if (hours <= 24) {
            if (hours == 1) {
                return "an hour ago";
            } else {
                return hours + " hrs ago";
            }
        }
        //Days
        else if (days <= 7) {
            if (days == 1) {
                return "yesterday";
            } else {
                return days + " days ago";
            }
        }
        //Weeks
        else if (weeks <= 4.3) {
            if (weeks == 1) {
                return "a week ago";
            } else {
                return weeks + " weeks ago";
            }
        }
        //Months
        else if (months <= 12) {
            if (months == 1) {
                return "a month ago";
            } else {
                return months + " months ago";
            }
        }
        //Years
        else {
            if (years == 1) {
                return "one year ago";
            } else {
                return years + " years ago";
            }
        }
    }

1) Tutaj time_ago jest w mikrosekundach


4

W oparciu o kilka odpowiedzi tutaj utworzyłem następujące informacje dla mojego przypadku użycia.

Przykładowe użycie:

String relativeDate = String.valueOf(
                TimeUtils.getRelativeTime( 1000L * myTimeInMillis() ));

import java.util.Arrays;
import java.util.List;

import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * Utilities for dealing with dates and times
 */
public class TimeUtils {

    public static final List<Long> times = Arrays.asList(
        DAYS.toMillis(365),
        DAYS.toMillis(30),
        DAYS.toMillis(7),
        DAYS.toMillis(1),
        HOURS.toMillis(1),
        MINUTES.toMillis(1),
        SECONDS.toMillis(1)
    );

    public static final List<String> timesString = Arrays.asList(
        "yr", "mo", "wk", "day", "hr", "min", "sec"
    );

    /**
     * Get relative time ago for date
     *
     * NOTE:
     *  if (duration > WEEK_IN_MILLIS) getRelativeTimeSpanString prints the date.
     *
     * ALT:
     *  return getRelativeTimeSpanString(date, now, SECOND_IN_MILLIS, FORMAT_ABBREV_RELATIVE);
     *
     * @param date String.valueOf(TimeUtils.getRelativeTime(1000L * Date/Time in Millis)
     * @return relative time
     */
    public static CharSequence getRelativeTime(final long date) {
        return toDuration( Math.abs(System.currentTimeMillis() - date) );
    }

    private static String toDuration(long duration) {
        StringBuilder sb = new StringBuilder();
        for(int i=0;i< times.size(); i++) {
            Long current = times.get(i);
            long temp = duration / current;
            if (temp > 0) {
                sb.append(temp)
                  .append(" ")
                  .append(timesString.get(i))
                  .append(temp > 1 ? "s" : "")
                  .append(" ago");
                break;
            }
        }
        return sb.toString().isEmpty() ? "now" : sb.toString();
    }
}

Jest to bardzo przydatne, bardzo dziękuję.
Haya Akkad

3

Joda czasu pakiet ma pojęcie okresów . Możesz wykonywać działania arytmetyczne z okresami i datami.

Z dokumentów :

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = new  Period().withDays(2).withHours(12);
  return datetimeRented.plus(rentalPeriod).isBeforeNow();
}


2

Jest to lepszy kod, jeśli weźmiemy pod uwagę wydajność, ponieważ zmniejsza liczbę obliczeń. Powód Minuty są obliczane tylko wtedy, gdy liczba sekund jest większa niż 60, a godziny są obliczane tylko wtedy, gdy liczba minut jest większa niż 60 i tak dalej ...

class timeAgo {

static String getTimeAgo(long time_ago) {
    time_ago=time_ago/1000;
    long cur_time = (Calendar.getInstance().getTimeInMillis())/1000 ;
    long time_elapsed = cur_time - time_ago;
    long seconds = time_elapsed;
   // Seconds
    if (seconds <= 60) {
        return "Just now";
    }
    //Minutes
    else{
        int minutes = Math.round(time_elapsed / 60);

        if (minutes <= 60) {
            if (minutes == 1) {
                return "a minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else {
            int hours = Math.round(time_elapsed / 3600);
            if (hours <= 24) {
                if (hours == 1) {
                    return "An hour ago";
                } else {
                    return hours + " hrs ago";
                }
            }
            //Days
            else {
                int days = Math.round(time_elapsed / 86400);
                if (days <= 7) {
                    if (days == 1) {
                        return "Yesterday";
                    } else {
                        return days + " days ago";
                    }
                }
                //Weeks
                else {
                    int weeks = Math.round(time_elapsed / 604800);
                    if (weeks <= 4.3) {
                        if (weeks == 1) {
                            return "A week ago";
                        } else {
                            return weeks + " weeks ago";
                        }
                    }
                    //Months
                    else {
                        int months = Math.round(time_elapsed / 2600640);
                        if (months <= 12) {
                            if (months == 1) {
                                return "A month ago";
                            } else {
                                return months + " months ago";
                            }
                        }
                        //Years
                        else {
                            int years = Math.round(time_elapsed / 31207680);
                            if (years == 1) {
                                return "One year ago";
                            } else {
                                return years + " years ago";
                            }
                        }
                    }
                }
            }
        }
    }

}

}

1
Jeśli pracujesz na Androidzie, możesz użyć tego: android.text.format.DateUtils.getRelativeTimeSpanString (milisekundy)
Wajid Ali

2

java.time

The Answer autorstwa Habsq ma dobry pomysł, ale złe metody.

Dla przedziału czasu niezwiązanego z osią czasu w skali lata-miesiące-dni użyj Period. W przypadku dni oznaczających 24-godzinne fragmenty czasu niezwiązane z kalendarzem i godziny-minuty-sekundy użyj Duration. Mieszanie obu skal rzadko ma sens.

Duration

Zacznij od pobrania aktualnego momentu, jak widać w UTC , przy użyciu Instantklasy.

Instant now = Instant.now();  // Capture the current moment as seen in UTC.
Instant then = now.minus( 8L , ChronoUnit.HOURS ).minus( 8L , ChronoUnit.MINUTES ).minus( 8L , ChronoUnit.SECONDS );
Duration d = Duration.between( then , now );

Generuj tekst na godziny, minuty i sekundy.

// Generate text by calling `to…Part` methods.
String output = d.toHoursPart() + " hours ago\n" + d.toMinutesPart() + " minutes ago\n" + d.toSecondsPart() + " seconds ago";

Zrzuć na konsolę.

System.out.println( "From: " + then + " to: " + now );
System.out.println( output );

Od: 2019-06-04T11: 53: 55.714965Z do: 2019-06-04T20: 02: 03.714965Z

8 godzin temu

8 minut temu

8 sekund temu

Period

Zacznij od uzyskania aktualnej daty.

Strefa czasowa ma kluczowe znaczenie przy ustalaniu daty. W dowolnym momencie data różni się na całym świecie według strefy. Na przykład, kilka minut po północy w Paryżu Francja jest nowym dniem, podczas gdy w Montrealu Quebec wciąż trwa „wczoraj” .

Jeśli nie określono strefy czasowej, maszyna JVM niejawnie stosuje swoją bieżącą domyślną strefę czasową. To ustawienie domyślne może się zmienić w dowolnym momencie w trakcie działania (!), Więc wyniki mogą się różnić. Lepiej jest jawnie określić żądaną / oczekiwaną strefę czasową jako argument. Jeśli jest to krytyczne, potwierdź strefę ze swoim użytkownikiem.

Określ prawidłową nazwę strefy czasowej w formacie Continent/Region, takie jak America/Montreal, Africa/Casablancalub Pacific/Auckland. Nigdy nie używaj skrótów składających się z 2-4 liter, takich jak ESTlub, ISTponieważ nie są to prawdziwe strefy czasowe, nie są standaryzowane, a nawet nie są unikalne (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Odtwórz datę sprzed ośmiu dni, miesięcy i lat.

LocalDate then = today.minusYears( 8 ).minusMonths( 8 ).minusDays( 7 ); // Notice the 7 days, not 8, because of granularity of months. 

Oblicz czas, który upłynął.

Period p = Period.between( then , today );

Zbuduj ciąg kawałków „dawniej”.

String output = p.getDays() + " days ago\n" + p.getMonths() + " months ago\n" + p.getYears() + " years ago";

Zrzuć na konsolę.

System.out.println( "From: " + then + " to: " + today );
System.out.println( output );

Od: 2010-09-27 do: 2019-06-04

8 dni temu

8 miesięcy temu

8 lat temu


Informacje o java.time

Struktura java.time jest wbudowana w Javę 8 i nowsze. Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak java.util.Date, Calendar, i SimpleDateFormat.

Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj Stack Overflow, aby znaleźć wiele przykładów i wyjaśnień. Specyfikacja to JSR 310 .

Projekt Joda-Time , obecnie w trybie konserwacji , zaleca migrację do klas java.time .

Możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie ma potrzeby stosowania ciągów ani java.sql.*klas.

Skąd wziąć klasy java.time?

Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem doświadczalnym dla ewentualnych przyszłych dodatków do java.time. Można znaleźć kilka przydatnych klas tutaj takie jak Interval, YearWeek, YearQuarter, i więcej .


Dziękuję bardzo!
Ticherhaz

1

Po długich poszukiwaniach znalazłem to.

    public class GetTimeLapse {
    public static String getlongtoago(long createdAt) {
        DateFormat userDateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
        DateFormat dateFormatNeeded = new SimpleDateFormat("MM/dd/yyyy HH:MM:SS");
        Date date = null;
        date = new Date(createdAt);
        String crdate1 = dateFormatNeeded.format(date);

        // Date Calculation
        DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        crdate1 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(date);

        // get current date time with Calendar()
        Calendar cal = Calendar.getInstance();
        String currenttime = dateFormat.format(cal.getTime());

        Date CreatedAt = null;
        Date current = null;
        try {
            CreatedAt = dateFormat.parse(crdate1);
            current = dateFormat.parse(currenttime);
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Get msec from each, and subtract.
        long diff = current.getTime() - CreatedAt.getTime();
        long diffSeconds = diff / 1000;
        long diffMinutes = diff / (60 * 1000) % 60;
        long diffHours = diff / (60 * 60 * 1000) % 24;
        long diffDays = diff / (24 * 60 * 60 * 1000);

        String time = null;
        if (diffDays > 0) {
            if (diffDays == 1) {
                time = diffDays + "day ago ";
            } else {
                time = diffDays + "days ago ";
            }
        } else {
            if (diffHours > 0) {
                if (diffHours == 1) {
                    time = diffHours + "hr ago";
                } else {
                    time = diffHours + "hrs ago";
                }
            } else {
                if (diffMinutes > 0) {
                    if (diffMinutes == 1) {
                        time = diffMinutes + "min ago";
                    } else {
                        time = diffMinutes + "mins ago";
                    }
                } else {
                    if (diffSeconds > 0) {
                        time = diffSeconds + "secs ago";
                    }
                }

            }

        }
        return time;
    }
}

1

Dla Androida Dokładnie tak, jak powiedział Ravi, ale ponieważ wiele osób chce po prostu skopiować i wkleić to, co jest tutaj.

  try {
      SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
      Date dt = formatter.parse(date_from_server);
      CharSequence output = DateUtils.getRelativeTimeSpanString (dt.getTime());
      your_textview.setText(output.toString());
    } catch (Exception ex) {
      ex.printStackTrace();
      your_textview.setText("");
    }

Wyjaśnienie dla osób, które mają więcej czasu

  1. Masz dane skądś. Najpierw musisz dowiedzieć się, jaki jest format.

Dawny. Otrzymuję dane z serwera w formacie Wed, 27 Jan 2016 09:32:35 GMT [to prawdopodobnie NIE Twój przypadek]

to jest tłumaczone na

SimpleDateFormat formatter = nowy SimpleDateFormat ("EEE, dd MMM rrrr HH: mm: ss Z");

skąd to wiem Przeczytaj dokumentację tutaj.

Po przeanalizowaniu otrzymuję datę. datę, którą umieściłem w getRelativeTimeSpanString (bez żadnych dodatkowych parametrów jest w porządku, domyślnie minuty)

Otrzymasz wyjątek, jeśli nie wymyśliłeś prawidłowego ciągu parsowania , Coś w rodzaju: wyjątek przy znaku 5 . Spójrz na znak 5 i popraw początkowy ciąg analizy. . Możesz uzyskać inny wyjątek, powtarzaj te kroki, aż uzyskasz prawidłową formułę.


1
private const val SECOND_MILLIS = 1
private const val MINUTE_MILLIS = 60 * SECOND_MILLIS
private const val HOUR_MILLIS = 60 * MINUTE_MILLIS
private const val DAY_MILLIS = 24 * HOUR_MILLIS

object TimeAgo {

fun timeAgo(time: Int): String {

    val now = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())
    if (time > now || time <= 0) {
        return "in the future"
    }

    val diff = now - time
    return when {
        diff < MINUTE_MILLIS -> "Just now"
        diff < 2 * MINUTE_MILLIS -> "a minute ago"
        diff < 60 * MINUTE_MILLIS -> "${diff / MINUTE_MILLIS} minutes ago"
        diff < 2 * HOUR_MILLIS -> "an hour ago"
        diff < 24 * HOUR_MILLIS -> "${diff / HOUR_MILLIS} hours ago"
        diff < 48 * HOUR_MILLIS -> "yesterday"
        else -> "${diff / DAY_MILLIS} days ago"
    }
}

}

Połączenie

val String = timeAgo (unixTimeStamp)

aby uzyskać czas temu w Kotlinie


0

Oto moja implementacja w Javie

    public static String relativeDate(Date date){
    Date now=new Date();
    if(date.before(now)){
    int days_passed=(int) TimeUnit.MILLISECONDS.toDays(now.getTime() - date.getTime());
    if(days_passed>1)return days_passed+" days ago";
    else{
        int hours_passed=(int) TimeUnit.MILLISECONDS.toHours(now.getTime() - date.getTime());
        if(hours_passed>1)return days_passed+" hours ago";
        else{
            int minutes_passed=(int) TimeUnit.MILLISECONDS.toMinutes(now.getTime() - date.getTime());
            if(minutes_passed>1)return minutes_passed+" minutes ago";
            else{
                int seconds_passed=(int) TimeUnit.MILLISECONDS.toSeconds(now.getTime() - date.getTime());
                return seconds_passed +" seconds ago";
            }
        }
    }

    }
    else
    {
        return new SimpleDateFormat("HH:mm:ss MM/dd/yyyy").format(date).toString();
    }
  }

0

mi to pasuje

public class TimeDifference {
    int years;
    int months;
    int days;
    int hours;
    int minutes;
    int seconds;
    String differenceString;

    public TimeDifference(@NonNull Date curdate, @NonNull Date olddate) {

        float diff = curdate.getTime() - olddate.getTime();
        if (diff >= 0) {
            int yearDiff = Math.round((diff / (AppConstant.aLong * AppConstant.aFloat)) >= 1 ? (diff / (AppConstant.aLong * AppConstant.aFloat)) : 0);
            if (yearDiff > 0) {
                years = yearDiff;
                setDifferenceString(years + (years == 1 ? " year" : " years") + " ago");
            } else {
                int monthDiff = Math.round((diff / AppConstant.aFloat) >= 1 ? (diff / AppConstant.aFloat) : 0);
                if (monthDiff > 0) {
                    if (monthDiff > AppConstant.ELEVEN) {
                        monthDiff = AppConstant.ELEVEN;
                    }
                    months = monthDiff;
                    setDifferenceString(months + (months == 1 ? " month" : " months") + " ago");
                } else {
                    int dayDiff = Math.round((diff / (AppConstant.bFloat)) >= 1 ? (diff / (AppConstant.bFloat)) : 0);
                    if (dayDiff > 0) {
                        days = dayDiff;
                        if (days == AppConstant.THIRTY) {
                            days = AppConstant.TWENTYNINE;
                        }
                        setDifferenceString(days + (days == 1 ? " day" : " days") + " ago");
                    } else {
                        int hourDiff = Math.round((diff / (AppConstant.cFloat)) >= 1 ? (diff / (AppConstant.cFloat)) : 0);
                        if (hourDiff > 0) {
                            hours = hourDiff;
                            setDifferenceString(hours + (hours == 1 ? " hour" : " hours") + " ago");
                        } else {
                            int minuteDiff = Math.round((diff / (AppConstant.dFloat)) >= 1 ? (diff / (AppConstant.dFloat)) : 0);
                            if (minuteDiff > 0) {
                                minutes = minuteDiff;
                                setDifferenceString(minutes + (minutes == 1 ? " minute" : " minutes") + " ago");
                            } else {
                                int secondDiff = Math.round((diff / (AppConstant.eFloat)) >= 1 ? (diff / (AppConstant.eFloat)) : 0);
                                if (secondDiff > 0) {
                                    seconds = secondDiff;
                                } else {
                                    seconds = 1;
                                }
                                setDifferenceString(seconds + (seconds == 1 ? " second" : " seconds") + " ago");
                            }
                        }
                    }

                }
            }

        } else {
            setDifferenceString("Just now");
        }

    }

    public String getDifferenceString() {
        return differenceString;
    }

    public void setDifferenceString(String differenceString) {
        this.differenceString = differenceString;
    }

    public int getYears() {
        return years;
    }

    public void setYears(int years) {
        this.years = years;
    }

    public int getMonths() {
        return months;
    }

    public void setMonths(int months) {
        this.months = months;
    }

    public int getDays() {
        return days;
    }

    public void setDays(int days) {
        this.days = days;
    }

    public int getHours() {
        return hours;
    }

    public void setHours(int hours) {
        this.hours = hours;
    }

    public int getMinutes() {
        return minutes;
    }

    public void setMinutes(int minutes) {
        this.minutes = minutes;
    }

    public int getSeconds() {
        return seconds;
    }

    public void setSeconds(int seconds) {
        this.seconds = seconds;
    } }

0

To jest bardzo podstawowy skrypt. łatwo jest improwizować.
Wynik: (XXX godzin temu) lub (XX dni temu / wczoraj / dziś)

<span id='hourpost'></span>
,or
<span id='daypost'></span>

<script>
var postTime = new Date('2017/6/9 00:01'); 
var now = new Date();
var difference = now.getTime() - postTime.getTime();
var minutes = Math.round(difference/60000);
var hours = Math.round(minutes/60);
var days = Math.round(hours/24);

var result;
if (days < 1) {
result = "Today";
} else if (days < 2) {
result = "Yesterday";
} else {
result = days + " Days ago";
}

document.getElementById("hourpost").innerHTML = hours + "Hours Ago" ;
document.getElementById("daypost").innerHTML = result ;
</script>

0

w tym celu zrobiłem Just Now, seconds ago, min ago, hrs ago, days ago, weeks ago, months ago, years agow tym przykładzie, możesz przeanalizować datę taką 2018-09-05T06:40:46.183Zlub inną, jak poniżej

dodaj poniższą wartość w string.xml

  <string name="lbl_justnow">Just Now</string>
    <string name="lbl_seconds_ago">seconds ago</string>
    <string name="lbl_min_ago">min ago</string>
    <string name="lbl_mins_ago">mins ago</string>
    <string name="lbl_hr_ago">hr ago</string>
    <string name="lbl_hrs_ago">hrs ago</string>
    <string name="lbl_day_ago">day ago</string>
    <string name="lbl_days_ago">days ago</string>
    <string name="lbl_lstweek_ago">last week</string>
    <string name="lbl_week_ago">weeks ago</string>
    <string name="lbl_onemonth_ago">1 month ago</string>
    <string name="lbl_month_ago">months ago</string>
    <string name="lbl_oneyear_ago" >last year</string>
    <string name="lbl_year_ago" >years ago</string>

kod java spróbuj poniżej

  public String getFormatDate(String postTime1) {
        Calendar cal=Calendar.getInstance();
        Date now=cal.getTime();
        String disTime="";
        try {
            Date postTime;
            //2018-09-05T06:40:46.183Z
            postTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(postTime1);

            long diff=(now.getTime()-postTime.getTime()+18000)/1000;

            //for months
            Calendar calObj = Calendar.getInstance();
            calObj.setTime(postTime);
            int m=calObj.get(Calendar.MONTH);
            calObj.setTime(now);

            SimpleDateFormat monthFormatter = new SimpleDateFormat("MM"); // output month

            int mNow = Integer.parseInt(monthFormatter.format(postTime));

            diff = diff-19800;

            if(diff<15) { //below 15 sec

                disTime = getResources().getString(R.string.lbl_justnow);
            } else if(diff<60) {

                //below 1 min
                disTime= diff+" "+getResources().getString(R.string.lbl_seconds_ago);
            } else if(diff<3600) {//below 1 hr

                // convert min
                long temp=diff/60;

                if(temp==1) {
                    disTime= temp + " " +getResources().getString(R.string.lbl_min_ago);
                } else {
                    disTime = temp  + " " +getResources().getString(R.string.lbl_mins_ago);
                }
            } else if(diff<(24*3600)) {// below 1 day

                // convert hr
                long temp= diff/3600;
                System.out.println("hey temp3:"+temp);
                if(temp==1) {
                    disTime = temp  + " " +getResources().getString(R.string.lbl_hr_ago);
                } else {
                    disTime = temp + " " +getResources().getString(R.string.lbl_hrs_ago);
                }
            } else if(diff<(24*3600*7)) {// below week

                // convert days
                long temp=diff/(3600*24);
                if (temp==1) {
                    //  disTime = "\nyesterday";
                    disTime = temp + " " +getResources().getString(R.string.lbl_day_ago);
                } else {
                    disTime = temp + " " +getResources().getString(R.string.lbl_days_ago);
                }
            } else if(diff<((24*3600*28))) {// below month

                // convert week
                long temp=diff/(3600*24*7);
                if (temp <= 4) {

                    if (temp < 1) {
                        disTime = getResources().getString(R.string.lbl_lstweek_ago);
                    }else{
                        disTime = temp + " " + getResources().getString(R.string.lbl_week_ago);
                    }

                } else {
                    int diffMonth = mNow - m;
                    Log.e("count : ", String.valueOf(diffMonth));
                    disTime = diffMonth + " " + getResources().getString(R.string.lbl_month_ago);
                }
            }else if(diff<((24*3600*365))) {// below year

                // convert month
                long temp=diff/(3600*24*30);

                System.out.println("hey temp2:"+temp);
                if (temp <= 12) {

                    if (temp == 1) {
                        disTime = getResources().getString(R.string.lbl_onemonth_ago);
                    }else{
                        disTime = temp + " " + getResources().getString(R.string.lbl_month_ago);
                    }
                }

            }else if(diff>((24*3600*365))) { // above year

                // convert year
                long temp=diff/(3600*24*30*12);

                System.out.println("hey temp8:"+temp);

                if (temp == 1) {
                    disTime = getResources().getString(R.string.lbl_oneyear_ago);
                }else{
                    disTime = temp + " " + getResources().getString(R.string.lbl_year_ago);
                }
            }

        } catch(Exception e) {
            e.printStackTrace();
        }

        return disTime;
    }

Jeśli pracujesz na Androidzie, możesz użyć tego: android.text.format.DateUtils.getRelativeTimeSpanString (milisekundy)
Wajid Ali

0

Możesz użyć biblioteki Java RelativeDateTimeFormatter , robi to dokładnie:

RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance();
 fmt.format(1, Direction.NEXT, RelativeUnit.DAYS); // "in 1 day"
 fmt.format(3, Direction.NEXT, RelativeUnit.DAYS); // "in 3 days"
 fmt.format(3.2, Direction.LAST, RelativeUnit.YEARS); // "3.2 years ago"

 fmt.format(Direction.LAST, AbsoluteUnit.SUNDAY); // "last Sunday"
 fmt.format(Direction.THIS, AbsoluteUnit.SUNDAY); // "this Sunday"
 fmt.format(Direction.NEXT, AbsoluteUnit.SUNDAY); // "next Sunday"
 fmt.format(Direction.PLAIN, AbsoluteUnit.SUNDAY); // "Sunday"

 fmt.format(Direction.LAST, AbsoluteUnit.DAY); // "yesterday"
 fmt.format(Direction.THIS, AbsoluteUnit.DAY); // "today"
 fmt.format(Direction.NEXT, AbsoluteUnit.DAY); // "tomorrow"

 fmt.format(Direction.PLAIN, AbsoluteUnit.NOW); // "now"

1
To jest biblioteka Androida, a nie biblioteka Java.
Madbreaks

0

Używam Instant, Date i DateTimeUtils. Dane (data), które są przechowywane w bazie danych w typie String, a następnie konwertowane na Instant.

    /*
    This method is to display ago.
    Example: 3 minutes ago.
    I already implement the latest which is including the Instant.
    Convert from String to Instant and then parse to Date.
     */
    public String convertTimeToAgo(String dataDate) {
    //Initialize
    String conversionTime = null;
    String suffix = "Yang Lalu";
    Date pastTime;
    //Parse from String (which is stored as Instant.now().toString()
    //And then convert to become Date
    Instant instant = Instant.parse(dataDate);
    pastTime = DateTimeUtils.toDate(instant);

    //Today date
    Date nowTime = new Date();

    long dateDiff = nowTime.getTime() - pastTime.getTime();
    long second = TimeUnit.MILLISECONDS.toSeconds(dateDiff);
    long minute = TimeUnit.MILLISECONDS.toMinutes(dateDiff);
    long hour = TimeUnit.MILLISECONDS.toHours(dateDiff);
    long day = TimeUnit.MILLISECONDS.toDays(dateDiff);

    if (second < 60) {
        conversionTime = second + " Saat " + suffix;
    } else if (minute < 60) {
        conversionTime = minute + " Minit " + suffix;
    } else if (hour < 24) {
        conversionTime = hour + " Jam " + suffix;
    } else if (day >= 7) {
        if (day > 30) {
            conversionTime = (day / 30) + " Bulan " + suffix;
        } else if (day > 360) {
            conversionTime = (day / 360) + " Tahun " + suffix;
        } else {
            conversionTime = (day / 7) + " Minggu " + suffix;
        }
    } else if (day < 7) {
        conversionTime = day + " Hari " + suffix;
    }
    return conversionTime;
    }

1
Używasz okropnych starych klas daty i czasu, które lata temu zostały wyparte przez klasy java.time .
Basil Bourque

@BasilBourque Nadal nie mogę znaleźć najnowszego sposobu, aby to zrobić.
Ticherhaz

@BasilBourque Dodałem kod, żeby to zrozumieć. github.com/ticherhaz/tarikhmasa
Ticherhaz

0

Poniższe rozwiązania są w czystej Javie:

Opcja 1: bez zaokrąglania i tylko największy kontener czasu

Następująca funkcja wyświetli tylko największy kontener czasu, na przykład, jeśli prawdziwy czas, który upłynął "1 month 14 days ago", to ta funkcja będzie wyświetlana tylko "1 month ago". Ta funkcja również zawsze zaokrągla w dół, więc czas odpowiadający funkcji "50 days ago"będzie wyświetlany jako"1 month"

public String formatTimeAgo(long millis) {
        String[] ids = new String[]{"second","minute","hour","day","month","year"};

        long seconds = millis / 1000;
        long minutes = seconds / 60;
        long hours = minutes / 60;
        long days = hours / 24;
        long months = days / 30;
        long years = months / 12;

        ArrayList<Long> times = new ArrayList<>(Arrays.asList(years, months, days, hours, minutes, seconds));

        for(int i = 0; i < times.size(); i++) {
            if(times.get(i) != 0) {
                long value = times.get(i).intValue();

                return value + " " + ids[ids.length - 1 - i] + (value == 1 ? "" : "s") + " ago";
            }
        }

        return "0 seconds ago";
    }

Opcja 2: z zaokrągleniem

Po prostu zawiń kontener czasu, który chcesz zaokrąglić, instrukcją Math.round (...), więc jeśli chcesz zaokrąglić 50 daysdo 2 months, zmodyfikuj long months = days / 30dolong months = Math.round(days / 30.0)


1
Korzystanie Durationz jego to…Partmetod byłoby znacznie łatwiejsze, jak pokazano w mojej odpowiedzi .
Basil Bourque,

0

Oto mój przypadek testowy, mam nadzieję, że pomoże:

    val currentCalendar = Calendar.getInstance()
    currentCalendar.set(2019, 6, 2, 5, 31, 0)

    val targetCalendar = Calendar.getInstance()
    targetCalendar.set(2019, 6, 2, 5, 30, 0)

    val diffTs = currentCalendar.timeInMillis - targetCalendar.timeInMillis
    val diffMins = TimeUnit.MILLISECONDS.toMinutes(diffTs)
    val diffHours = TimeUnit.MILLISECONDS.toHours(diffTs)
    val diffDays = TimeUnit.MILLISECONDS.toDays(diffTs)
    val diffWeeks = TimeUnit.MILLISECONDS.toDays(diffTs) / 7
    val diffMonths = TimeUnit.MILLISECONDS.toDays(diffTs) / 30
    val diffYears = TimeUnit.MILLISECONDS.toDays(diffTs) / 365

    val newTs = when {
        diffYears >= 1 -> "Years $diffYears"
        diffMonths >= 1 -> "Months $diffMonths"
        diffWeeks >= 1 -> "Weeks $diffWeeks"
        diffDays >= 1 -> "Days $diffDays"
        diffHours >= 1 -> "Hours $diffHours"
        diffMins >= 1 -> "Mins $diffMins"
        else -> "now"
    }

1
Straszliwa Calendarklasa została wyparta lat temu przez nowoczesne java.time klas wraz z przyjęciem JSR 310 . Słaba rada w 2019 r.
Basil Bourque

Musiałeś mieć na myśli var, nie val.
Basil Bourque

0

Funkcja getrelativeDateTime poda datę i godzinę, jak widać w powiadomieniu Whatsapp.
Aby uzyskać przyszłą względną datę i godzinę, dodaj dla niej warunki. Jest to tworzone specjalnie w celu uzyskania daty i godziny, takiej jak powiadomienie Whatsapp.

private static String getRelativeDateTime(long date) {
    SimpleDateFormat DateFormat = new SimpleDateFormat("MMM dd, yyyy", Locale.getDefault());
    SimpleDateFormat TimeFormat = new SimpleDateFormat(" hh:mm a", Locale.getDefault());
    long now = Calendar.getInstance().getTimeInMillis();
    long startOfDay = StartOfDay(Calendar.getInstance().getTime());
    String Day = "";
    String Time = "";
    long millSecInADay = 86400000;
    long oneHour = millSecInADay / 24;
    long differenceFromNow = now - date;

    if (date > startOfDay) {
        if (differenceFromNow < (oneHour)) {
            int minute = (int) (differenceFromNow / (60000));
            if (minute == 0) {
                int sec = (int) differenceFromNow / 1000;
                if (sec == 0) {
                    Time = "Just Now";
                } else if (sec == 1) {
                    Time = sec + " second ago";
                } else {
                    Time = sec + " seconds ago";
                }
            } else if (minute == 1) {
                Time = minute + " minute ago";
            } else if (minute < 60) {
                Time = minute + " minutes ago";
            }
        } else {
            Day = "Today, ";
        }
    } else if (date > (startOfDay - millSecInADay)) {
        Day = "Yesterday, ";
    } else if (date > (startOfDay - millSecInADay * 7)) {
        int days = (int) (differenceFromNow / millSecInADay);
        Day = days + " Days ago, ";
    } else {
        Day = DateFormat.format(date);
    }
    if (Time.isEmpty()) {
        Time = TimeFormat.format(date);
    }
    return Day + Time;
}

public static long StartOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return calendar.getTimeInMillis();
}

Dzięki za chęć udziału. Nie jest to dokładnie to, o co pytano, ale może ktoś może to wykorzystać. Ani ten ktoś, ani nikt inny nie powinien chcieć używać SimpleDateFormati Calendarchociaż. Te klasy są źle zaprojektowane i dawno przestarzałe. Zamiast tego przeczytaj odpowiedzi wykorzystujące java.time, nowoczesny interfejs API daty i czasu języka Java.
Ole VV

0

Ze względu na brak prostoty i zaktualizowanej odpowiedzi, następuje nowsza wersja Java 8 i nowszych

import java.time.*;
import java.time.temporal.*;

public class Time {
    public static void main(String[] args) {

        System.out.println(LocalTime.now().minus(8, ChronoUnit.MINUTES));
        System.out.println(LocalTime.now().minus(8, ChronoUnit.HOURS));
        System.out.println(LocalDateTime.now().minus(8, ChronoUnit.DAYS));
        System.out.println(LocalDateTime.now().minus(8, ChronoUnit.MONTHS));
    }
}

Jest to wersja korzystająca z Java Time API, która próbuje rozwiązać problemy z przeszłości w zakresie obsługi daty i godziny.

Javadoc

wersja 8 https://docs.oracle.com/javase/8/docs/api/index.html?java/time/package-summary.html

wersja 11 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html

Samouczek W3Schools - https://www.w3schools.com/java/java_date.asp

Artykuł DZone - https://dzone.com/articles/java-8-date-and-time

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.