¿Cómo calcular "hace tiempo" en Java?


Respuestas:


177

Echa un vistazo a la biblioteca PrettyTime .

Es bastante simple de usar:

import org.ocpsoft.prettytime.PrettyTime;

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

También puede pasar una configuración regional para mensajes internacionalizados:

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

Como se señaló en los comentarios, Android tiene esta funcionalidad integrada en la android.text.format.DateUtilsclase.


229
En caso de que esté trabajando en Android, puede usar esto: android.text.format.DateUtils # getRelativeTimeSpanString ()
Somatik

¿Puede agregar alguna descripción más a su respuesta? La respuesta de solo enlace no es buena por ahora.
Ajay S

@Somatik si necesita obtener esto en una plataforma que no sea Android, puede ver esa clase en AOSP.
greg7gkb

@ataylor ¿cómo se usa esto en Android?
Hardik Parmar

getRelativeTimeSpanString no es ideal para todas las situaciones y es por eso que creé mi propia clase basada en muchos de los ejemplos aquí. Vea mi solución a continuación: stackoverflow.com/a/37042254/468360
Codeversed

67

¿Has considerado la enumeración de TimeUnit ? Puede ser bastante útil para este tipo de cosas.

    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();
    }

44
No creo que esta sea una respuesta completa ya que las unidades de tiempo son independientes. Por ejemplo, el tiempo de milisegundos es solo minutos * 60 * 1000. Debe disminuir de cada unidad de tiempo la siguiente unidad de tiempo más grande (después de convertirla en la unidad de tiempo más baja) para poder usarla en un "tiempo atrás" " cuerda.
Nativ

@Benj - ¿Es correcto? solución anterior? porque una vez está en formato de 12 horas y otra hora está en formato de 24 horas. Déjame saber tus comentarios para mi consulta. Gracias por adelantado.
Swift

sin embargo, esto es incorrecto ... cada unidad es independiente de la otra como ya se mencionó.
Jonathan Laliberte el

1
Android lo hace por usted En caso de que esté trabajando en Android, puede usar esto: android.text.format.DateUtils.getRelativeTimeSpanString (milisegundos)
Wajid Ali el

50

Tomo las respuestas de RealHowTo y Ben J y hago mi propia versión:

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));
}}

que imprimirá lo siguiente

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

Realmente genial. Y es realmente fácil agregar otras unidades de tiempo como semana (s)
Piotr

1
Este merece más votos a favor. En primer lugar, no se necesita biblioteca. Todavía está limpio, elegante y fácil de cambiar.
fangzhzh

pequeño error tipográfico: dentro de su código, hace referencia a las propiedades estáticas "Listas" en lugar de "TimeAgo". Lists.times.get (i) debería ser TimeAgo.get (i) ... y así sucesivamente
Diogo Gomes

2
Pequeña sugerencia: usar en .append(temp != 1 ? "s" : "")lugar de .append(temp > 1 ? "s" : "")porque 0 también debería tener ssufijo
berkus

1
@ShajeelAfzal sí, el parámetro de duración está en milisegundos pero es una diferencia entre tiempos, no un valor absoluto. Lo que está obteniendo es el tiempo transcurrido desde el 1 de enero de 1970, la fecha en que comenzó la marca de tiempo de Unix
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
         */
    }
}

more @ Formatee una duración en milisegundos en un formato legible para humanos


Terminé usando una versión revisada de esto. He publicado mis revisiones para ti.
David Blevins

55
David Blevins, más ejemplos sobre PrettyTime: stackoverflow.com/questions/3859288/… Big -1 por reinventar la rueda una vez más y no recomendar una biblioteca de terceros :-p
zakmck

9

Esto se basa en la respuesta de RealHowTo, así que si te gusta, dale un poco de amor también.

Esta versión limpia le permite especificar el rango de tiempo que le puede interesar.

También maneja la parte "y" un poco diferente. A menudo encuentro que al unir cadenas con un delimitador es más fácil omitir la lógica complicada y simplemente borrar el último delimitador cuando haya terminado.

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();
    }
}

Pequeño código para darle un giro:

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));
        }
    }

}

Lo que generará lo siguiente:

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 

Y en caso de que alguien lo necesite, aquí hay una clase que convertirá cualquier cadena como la anterior nuevamente en milisegundos . Es bastante útil para permitir que las personas especifiquen tiempos de espera de varias cosas en texto legible.


9

Hay una manera simple de hacer esto:

Digamos que quieres el tiempo hace 20 minutos:

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

Eso es..


1
En la mayoría de los casos, desea una pantalla "inteligente", es decir. en lugar de hace 5125 minutos, dices x días atrás.
PhiLho

7

Sobre soluciones integradas :

Java no tiene soporte incorporado para formatear tiempos relativos, tampoco Java-8 y su nuevo paquete java.time . Si solo necesita inglés y nada más y solo entonces una solución hecha a mano podría ser aceptable, vea la respuesta de @RealHowTo (aunque tiene la gran desventaja de no tener en cuenta la zona horaria para la traducción de deltas instantáneos a la hora local) ¡unidades!). De todos modos, si desea evitar soluciones alternativas complejas, especialmente para otras configuraciones regionales, necesita una biblioteca externa.

En este último caso, recomiendo usar mi biblioteca Time4J (o Time4A en Android). Ofrece la mayor flexibilidad y la mayor potencia i18n . La clase net.time4j.PrettyTime tiene siete métodos printRelativeTime...(...)para este propósito. Ejemplo usando un reloj de prueba como fuente de tiempo:

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)

Otro ejemplo usando java.time.Instantcomo entrada:

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

Esta biblioteca admite a través de su última versión (v4.17) 80 idiomas y también algunas configuraciones regionales específicas del país (especialmente para español, inglés, árabe, francés). Los datos i18n se basan principalmente en la versión más reciente de CLDR v29 . Otras razones importantes por las que usar esta biblioteca son un buen soporte para reglas plurales (que a menudo son diferentes del inglés en otros idiomas), un estilo de formato abreviado (por ejemplo: "Hace 1 segundo") y formas expresivas para tener en cuenta las zonas horarias . Time4J incluso es consciente de detalles tan exóticos como segundos intercalares en los cálculos de tiempos relativos (no es realmente importante, pero forma un mensaje relacionado con el horizonte de expectativas). La compatibilidad con Java-8existe debido a los métodos de conversión fácilmente disponibles para tipos como java.time.Instanto java.time.Period.

¿Hay algún inconveniente? Sólo dos.

  • La biblioteca no es pequeña (también debido a su gran repositorio de datos i18n).
  • La API no se conoce bien, por lo que el conocimiento y el soporte de la comunidad aún no están disponibles; de lo contrario, la documentación suministrada es bastante detallada y completa.

Alternativas (compactas):

Si busca una solución más pequeña y no necesita tantas funciones y está dispuesto a tolerar posibles problemas de calidad relacionados con i18n-data, entonces:

  • Recomendaría ocpsoft / PrettyTime (soporte para actualmente 32 idiomas (¿pronto 34?) Adecuados para trabajar java.util.Datesolo; vea la respuesta de @ataylor). Desafortunadamente, el CLDR estándar de la industria (del consorcio Unicode) con su gran experiencia en la comunidad no es una base de los datos i18n, por lo que otras mejoras o mejoras de datos pueden tomar un tiempo ...

  • Si está en Android, entonces la clase auxiliar android.text.format.DateUtils es una alternativa incorporada delgada (vea otros comentarios y respuestas aquí, con la desventaja de que no tiene soporte durante años y meses. Y estoy seguro de que solo A muy pocas personas les gusta el estilo API de esta clase auxiliar.

  • Si eres fanático de Joda-Time, entonces puedes ver su clase PeriodFormat (soporte para 14 idiomas en la versión v2.9.4, por otro lado: Joda-Time seguramente tampoco es compacto, así que lo menciono aquí solo por lo completo). Esta biblioteca no es una respuesta real porque los tiempos relativos no son compatibles en absoluto. Necesitará agregar el literal "ago" al menos (y eliminar manualmente todas las unidades inferiores de los formatos de lista generados, incómodo). A diferencia de Time4J o Android-DateUtils, no tiene soporte especial para abreviaturas o cambio automático de tiempos relativos a representaciones de tiempo absoluto. Al igual que PrettyTime, depende totalmente de las contribuciones no confirmadas de los miembros privados de la comunidad Java a sus datos i18n.


5

Si busca un simple "Hoy", "Ayer" o "Hace x días".

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

Usando el framework java.time integrado en Java 8 y posterior.

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
Esos Durationmétodos informan la duración completa como un número total de horas y como un número total de minutos. En Java 8, la clase extrañamente carecía de métodos para obtener cada parte de hora, minutos y segundos. Java 9 trae esos métodos, to…Part.
Basil Bourque


4

En caso de que esté desarrollando una aplicación para Android, proporciona la clase de utilidad DateUtils para todos esos requisitos. Eche un vistazo al método de utilidad DateUtils # getRelativeTimeSpanString () .

De los documentos para

CharSequence getRelativeTimeSpanString (mucho tiempo, mucho tiempo, mucho tiempo minResolution)

Devuelve una cadena que describe 'tiempo' como un tiempo relativo a 'ahora'. Los períodos de tiempo en el pasado están formateados como "hace 42 minutos". Los períodos de tiempo en el futuro están formateados como "En 42 minutos".

Se le pasa en tu timestampcomo el tiempo y System.currentTimeMillis()como ahora . Le minResolutionpermite especificar el intervalo de tiempo mínimo para informar.

Por ejemplo, un tiempo de 3 segundos en el pasado se informará como "hace 0 minutos" si se establece en MINUTE_IN_MILLIS. Pase uno de 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS, etc.


4

Puede usar esta función para calcular hace tiempo

 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) Aquí time_ago está en microsegundo


4

Basado en un montón de respuestas aquí, creé lo siguiente para mi caso de uso.

Ejemplo de uso:

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();
    }
}

Es muy útil, muchas gracias.
Haya Akkad

3

El paquete joda-time , tiene la noción de períodos . Puedes hacer aritmética con Periodos y DateTimes.

De los documentos :

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


2

Este es un código mejor si consideramos el rendimiento. Reduce la cantidad de cálculos. Motivo Los minutos se calculan solo si el número de segundos es mayor que 60 y las Horas se calculan solo si el número de minutos es mayor que 60 y así sucesivamente ...

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
En caso de que esté trabajando en Android, puede usar esto: android.text.format.DateUtils.getRelativeTimeSpanString (milisegundos)
Wajid Ali

2

java.time

La respuesta de Habsq tiene la idea correcta pero los métodos incorrectos.

Para un período de tiempo no conectado a la línea de tiempo en la escala de años-meses-días, use Period. Para los días que significan fragmentos de tiempo de 24 horas no relacionados con el calendario y las horas-minutos-segundos, use Duration. Mezclar las dos escalas rara vez tiene sentido.

Duration

Comience buscando el momento actual como se ve en UTC , utilizando la Instantclase.

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 );

Genera texto por horas, minutos y segundos.

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

Volcado a la consola.

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

Desde: 2019-06-04T11: 53: 55.714965Z hasta: 2019-06-04T20: 02: 03.714965Z

Hace 8 horas

Hace 8 minutos

Hace 8 segundos

Period

Comience por obtener la fecha actual.

Una zona horaria es crucial para determinar una fecha. Para cualquier momento dado, la fecha varía en todo el mundo por zona. Por ejemplo, unos minutos después de la medianoche en París, Francia es un nuevo día mientras todavía "ayer" en Montreal Québec .

Si no se especifica una zona horaria, la JVM aplica implícitamente su zona horaria predeterminada actual. Ese valor predeterminado puede cambiar en cualquier momento durante el tiempo de ejecución (!), Por lo que sus resultados pueden variar. Es mejor especificar su zona horaria deseada / esperada explícitamente como argumento. Si es crítico, confirme la zona con su usuario.

Especificar un nombre de zona horaria correcta en el formato de Continent/Region, por ejemplo America/Montreal, Africa/Casablancao Pacific/Auckland. Nunca use el 2-4 abreviatura de letras tales como ESTo IST, ya que son no verdaderas zonas de tiempo, no estandarizados, y ni siquiera único (!).

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

Recrea una fecha hace ocho días, meses y años.

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

Calcular el tiempo transcurrido.

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

Construye la cadena de piezas de "tiempo atrás".

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

Volcado a la consola.

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

Desde: 2010-09-27 hasta: 2019-06-04

hace 8 días

hace 8 meses

Hace 8 años


Acerca de java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como java.util.Date, Calendar, y SimpleDateFormat.

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No hay necesidad de cadenas, no hay necesidad de java.sql.*clases.

¿Dónde obtener las clases java.time?

El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Usted puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter, y más .


Muchas gracias!
Ticherhaz

1

Después de una larga investigación, encontré esto.

    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

Para Android Exactamente como dijo Ravi, pero dado que muchas personas solo quieren copiar y pegar la cosa aquí está.

  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("");
    }

Explicación para las personas que tienen más tiempo.

  1. Obtienes los datos de alguna parte. Primero tienes que descubrir su formato.

Ex. Recibo los datos de un servidor en el formato Mié, 27 de enero de 2016 09:32:35 GMT [este probablemente NO sea su caso]

esto se traduce en

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

como lo se Lea la documentación aquí.

Luego, después de analizarlo, tengo una cita. esa fecha la puse en getRelativeTimeSpanString (sin ningún parámetro adicional, estoy bien, por defecto a minutos)

Obtendrá una excepción si no descubrió la cadena de análisis correcta , algo como: excepción en el carácter 5 . Mira el carácter 5 y corrige tu cadena de análisis inicial. . Es posible que obtenga otra excepción, repita estos pasos hasta que tenga la fórmula correcta.


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"
    }
}

}

Llamada

val String = timeAgo (unixTimeStamp)

aprovechar el tiempo en Kotlin


0

Aquí está mi implementación Java de esto

    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

esto funciona para mi

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

Este es el guión muy básico. Es fácil de improvisar.
Resultado: (Hace XXX horas) o (Hace XX días / Ayer / Hoy)

<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

para esto que he hecho Just Now, seconds ago, min ago, hrs ago, days ago, weeks ago, months ago, years agoen este ejemplo, puede analizar la fecha como 2018-09-05T06:40:46.183Zesta o cualquier otra como a continuación

agregue debajo del valor en 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>

código java intente a continuación

  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;
    }

En caso de que esté trabajando en Android, puede usar esto: android.text.format.DateUtils.getRelativeTimeSpanString (milisegundos)
Wajid Ali

0

Puede usar la Biblioteca RelativeDateTimeFormatter de Java , hace exactamente eso:

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
Esa es una biblioteca de Android, no una biblioteca de Java.
Madbreaks

0

Estoy usando Instant, Date y DateTimeUtils. Los datos (fecha) que se almacenan en la base de datos en tipo de cadena y luego se convierten en instantáneos.

    /*
    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
Estás utilizando terribles clases antiguas de fecha y hora que fueron reemplazadas hace años por las clases java.time .
Basil Bourque

@BasilBourque Todavía no puedo encontrar la última forma de hacer esto.
Ticherhaz

@BasilBourque He agregado un código para que lo entienda. github.com/ticherhaz/tarikhmasa
Ticherhaz

0

Las siguientes soluciones están todas en Java puro:

Opción 1: sin redondeo y solo contenedor de tiempo más grande

La siguiente función solo mostrará el contenedor de tiempo más grande, por ejemplo, si el tiempo transcurrido verdadero es "1 month 14 days ago", esta función solo se mostrará "1 month ago". Esta función también siempre se redondeará hacia abajo, por lo que "50 days ago"se mostrará un tiempo equivalente a"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";
    }

Opción 2: con redondeo

Simplemente envuelva el contenedor de tiempo que desea redondear con una instrucción Math.round (...), por lo que si desea redondear 50 daysa 2 months, modifique long months = days / 30along months = Math.round(days / 30.0)


1
Usarlo Durationcon sus to…Partmétodos sería mucho más fácil, como se muestra en mi Respuesta .
Basil Bourque

0

Aquí está mi caso de prueba, espero que ayude:

    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
La Calendarclase terrible fue suplantada hace años por las modernas clases java.time con la adopción de JSR 310 . Mal consejo en 2019.
Basil Bourque

Debes haber querido decir var, no val.
Basil Bourque

0

La función getrelativeDateTime le dará la fecha y hora como ve en la notificación de Whatsapp.
Para obtener futuras fechas y horas relativas, agréguele condiciones. Esto se crea específicamente para obtener la fecha y hora como la notificación de 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();
}

Gracias por querer contribuir. No es exactamente lo que se pidió, pero tal vez alguien pueda usarlo. Sin embargo, ni a nadie ni a nadie debería querer usar SimpleDateFormaty Calendar, sin embargo. Esas clases están mal diseñadas y anticuadas. En su lugar, lea las respuestas que emplean java.time, la API moderna de fecha y hora de Java.
Ole VV

0

Por falta de simplicidad y respuesta actualizada, sigue la versión más reciente de Java 8 y posterior

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));
    }
}

Esta es la versión que utiliza la API de Java Time que intenta resolver problemas del pasado para tratar con Fecha y Hora.

Javadoc

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

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

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

Artículo de DZone: https://dzone.com/articles/java-8-date-and-time

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.