Pregunta

En Ruby on Rails, hay una característica que le permite tomar cualquier Fecha e imprimir la forma "hace mucho tiempo" que era.

Por ejemplo:

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

¿Hay una manera fácil de hacer esto en Java?

¿Fue útil?

Solución

Tome un vistazo a la biblioteca PrettyTime .

Es muy sencillo 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 de un local para los 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 incorporada en la android.text.format.DateUtils clase.

Otros consejos

¿Usted ha considerado el TimeUnit enumeración? Puede ser muy ú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();
    }

Tomo RealHowTo y Ben J respuestas y hacer 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á el 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
  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
         */
    }
}

Formatear una duración en milisegundos en un formato legible por humanos

Esto se basa en la respuesta de RealHowTo así que si usted gusta, Él / Ella tiene un poco de amor también.

Esta versión limpia le permite especificar el intervalo de tiempo que podría estar interesado en.

También se ocupa de la "y" parte un poco diferente. A menudo me encuentro cuando se unen las cadenas con un delimitador es ofter más fácil saltarse 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();
    }
}

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

}

¿Cuál es la salida 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 alguna vez lo necesita, aquí está una clase que convertirá cualquier cadena como el de arriba de nuevo en milisegundos . Es bastante útil para permitir a la gente para especificar los tiempos de espera de varias cosas en texto legible.

hay una forma sencilla de hacer esto:

Supongamos que desea que 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 todo ..

Si busca un simple "Hoy", "Yesterday" 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";
}

java.time

Uso de la java.time marco integrado en Java 8 y versiones posteriores.

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

Acerca de incorporada soluciones:

Java no tiene ningún soporte integrado para formatear tiempos relativos, tampoco Java-8 y su nueva java.time paquete. Si sólo necesita Inglés y nada más entonces y sólo entonces una solución hecha a mano podría ser aceptable - ver la respuesta de @RealHowTo (aunque tiene la fuerte desventaja de no tener en cuenta la zona horaria para la traducción de los deltas de inmediato a la hora local ¡unidades!). De todos modos, si se quiere evitar soluciones complejas de cosecha especialmente para otros lugares, entonces necesita una biblioteca externa.

En este último caso, recomiendo usar mi biblioteca Time4J (o Time4A en Android). Ofrece mayor flexibilidad y más i18n potencia . 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.Instant como entrada:

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

Esta biblioteca soportes a través de su última versión (v4.17) 80 idiomas y también algunos lugares específicos del país (especialmente para Español, Inglés, árabe, francés). Los datos i18n-se basan principalmente en la más nueva versión v29-CLDR . Otras razones importantes por las que utilizan esta biblioteca son buenas apoyo a las reglas plural (que a menudo son diferentes de Inglés en otros lugares), el estilo de formato abreviado (por ejemplo: "1 seg hace ") y expresivas formas de teniendo en cuenta las zonas horarias . Time4J siquiera se da cuenta de esos detalles exóticos como bisiestos segundo en los cálculos de tiempos relativos (no es realmente importante, pero forma un mensaje relacionado con el horizonte expectativa). La compatibilidad con Java-8 existe debido a fácilmente disponibles métodos de conversión para tipos como java.time.Instant o java.time.Period.

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

  • La biblioteca no es pequeño (también debido a su gran repositorio de i18n-datos).
  • La API no es muy conocido por lo que el conocimiento y apoyo de la comunidad no están disponibles todavía otra forma la documentación suministrada es bastante detallado y completo.

(resumen) alternativas:

Si usted busca una solución más pequeña y no necesita tantas características y están dispuestos a tolerar posibles problemas de calidad relacionados con la i18n-datos a continuación:

  • Yo recomendaría ocpsoft / PrettyTime (apoyo a los actualmente 32 idiomas (pronto 34) adecuados para el trabajo con sólo el java.util.Date -? Ver la respuesta de @ataylor). El CLDR estándar de la industria (del consorcio Unicode) con su fondo grande comunidad no es por desgracia una base de datos a fin de i18n-mejoras adicionales o mejoras de los datos puede tomar un tiempo ...

  • Si usted está en Android entonces la clase de ayuda android.text.format.DateUtils es una delgada incorporada alternativa (ver otros comentarios y respuestas aquí, con la desventaja de que tiene no hay soporte por años y meses. y estoy seguro de que sólo muy pocas personas como el estilo de la API de esta clase de ayuda.

  • Si usted es un fan de Joda-Time a continuación, se puede ver en su clase PeriodFormat (soporte para 14 idiomas en versión v2.9.4, en el otro lado: Joda- El tiempo es seguramente no compacta, también, así que menciono aquí simplemente para la corrección). Esta biblioteca no es una respuesta real, porque los tiempos relativos no son compatibles en absoluto. Usted tendrá que añadir "hace" el literal al menos (y pelar manualmente todas las unidades inferiores de formatos de lista generados - torpes). A diferencia de Time4J o Android-DateUtILS, que no tiene soporte especial para abreviaturas o la conmutación automática de tiempos relativos a las representaciones de tiempo absoluto. Al igual que PrettyTime, es totalmente dependiente de las contribuciones no confirmados de miembros privados de la comunidad de Java a su i18n-datos.

He creado un simple Java timeago puerto de la jquery-timeago plug-in que hace lo que usted está pidiendo.

TimeAgo time = new TimeAgo();
String minutes = time.timeAgo(System.currentTimeMillis() - (15*60*1000)); // returns "15 minutes ago"

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

A partir de la documentación para

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

  

Devuelve una cadena que describe el 'tiempo' como un tiempo en relación con el 'ahora'. lapsos de tiempo en el pasado tienen el formato "hace 42 minutos". lapsos de tiempo en el futuro tienen el formato "en 42 minutos".

Se le superación de su timestamp como tiempo y System.currentTimeMillis() como ahora . El minResolution le permite especificar el intervalo de tiempo mínimo de informe.

  

Por ejemplo, un tiempo de 3 segundos en el pasado serán reportados como "Hace 0 minutos" si esto se establece en MINUTE_IN_MILLIS. Pasar uno de 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS etc.

El href="http://joda-time.sourceforge.net/key_period.html" rel="nofollow"> paquete períodos . Puede realizar operaciones aritméticas con los períodos y DateTime.

Desde el docs :

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

Puede utilizar esta función para calcular el tiempo atrás

 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 es decir en microsegundo

Sobre la base de un montón de respuestas aquí, he creado el 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();
    }
}

No es bonito ... pero lo más cerca que puedo pensar es el uso de Joda-Time (como se describe en este post: Cómo calcular el tiempo transcurrido a partir de ahora con Joda Time?

Este es un código mejor si tenemos en cuenta performance.It reduce el número de cálculos. Razón Minutos se calculan sólo si el número de segundos es superior a 60 y Horas se calculan sólo si el número de minutos es superior a 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";
                            }
                        }
                    }
                }
            }
        }
    }

}

}

Después de una investigación a largo me encontré con 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;
    }
}

Para Android Exactamente igual que Ravi dijo, pero como mucha gente quiere acaba de copiar y pegar lo que 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. Obtener los datos de alguna parte. En primer lugar tiene que averiguar su formato.

Ex. Consigo los datos de un servidor en el formato Miér 27 Ene el año 2016 09:32:35 GMT [esto probablemente no es su caso]

esto se traduce en

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

¿Cómo lo sé? Lea la documentación de href="http://developer.android.com/reference/java/text/SimpleDateFormat.html" aquí.

A continuación, después de analizarlo consigo una fecha. esa fecha pongo en el getRelativeTimeSpanString (sin ningún parámetro adicional está bien para mí, para ser predeterminado a minutos)

Usted recibirá una excepción si no averiguar la análisis correcto de cadena , algo así como: excepción al personaje 5 . Mira personaje 5, y corregir la cadena de análisis inicial. . Usted puede obtener otra excepción, repita estos pasos hasta que tenga la fórmula correcta.

Aquí está mi implementación Java de este

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

funciona para mí

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

Este es el guión muy básico. es fácil improvisó.
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>

para este he Just Now, seconds ago, min ago, hrs ago, days ago, weeks ago, months ago, years ago hecho en este ejemplo se puede analizar como fecha 2018-09-05T06:40:46.183Z este o cualquier otro, como a continuación

añadir debajo de su valor en el 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 de Java intento por debajo

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

Puede utilizar la biblioteca de Java RelativeDateTimeFormatter , que 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"

Estoy usando la instantánea, la fecha y DateTimeUtils. Los datos (fecha) que se almacena en la base de datos en el tipo de cadena y luego convertir a ser inmediata.

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

java.time

El respuesta por Habsq tiene la idea correcta, pero los métodos equivocados.

En un lapso de tiempo de-desapegado de la línea de tiempo en la escala de años-mes-día, el uso Period . Para los días que significa trozos de 24 horas de tiempo no relacionadas al calendario y horas-minutos-segundos, el uso Duration . Mezclar las dos escalas rara vez tiene sentido.

Duration

Para comenzar, ir a buscar el momento actual como se ve en UTC , utilizando el Instant clase.

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

Generar texto para 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 );
  

De: 2019-06-04T11: 53: 55.714965Z a: 2019-06-04T20: 02: 03.714965Z

     

Hace 8 horas

     

Hace 8 minutos

     

Hace 8 segundos

Period

empezar por conseguir la fecha actual.

Una zona horaria es crucial en la determinación de una fecha. Por un 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 que todavía “ ayer”en Montréal Québec .

Si no se especifica la zona horaria, la JVM implícitamente aplica su zona horaria predeterminada actual. Eso predeterminado puede ser cambiar en cualquier momento durante el tiempo de ejecución (!), por lo que sus resultados pueden variar. Mejor para especificar su zona horaria deseada / esperada explícitamente como un argumento. Si crítico, confirmar la zona con su usuario.

adecuada zona horaria Nombre en el formato de Continent/Region, como America/Montreal, Africa/Casablanca o Pacific/Auckland. Nunca use el 2-4 abreviatura de letras tales como EST o IST ya que son no verdaderas zonas de tiempo, no estandarizados, y ni siquiera únicas (!).

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

recrear una fecha de 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 );

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

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 a: 04/06/2019

     

Hace 8 días

     

Hace 8 meses

     

Hace 8 años


Acerca de java.time

El java.time marco está incorporado en Java 8 y versiones posteriores. Estas clases suplantar a la problemática de edad legado clases de fecha y hora como java.util.Date , Calendar , y SimpleDateFormat .

Para saber más, Consulte la Oracle Tutorial . Y la búsqueda de desbordamiento de pila durante muchos ejemplos y explicaciones. Especificación es JSR 310 .

El Joda-Time proyecto, ahora en < a href = "https://en.wikipedia.org/wiki/Maintenance_mode" rel = "noreferrer nofollow"> el modo de mantenimiento , aconseja migración a la java.time clases .

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

¿Dónde obtener las clases java.time?

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

Esta función calculará en Java puro, sin embargo, esta función no muestra parciales como "1 hour, 3 minutes", se utilizará el valor más grande de contenedores (horas, días, meses, etc.) que pueda, y redondea al valor más cercano .

private String agoFromTime(long seconds) {
        long minutes = seconds / 60;
        long hours = seconds / 3600;
        long days = seconds / 86400;
        long years = seconds / (86400 * 365);

        String postfix;
        long result;
        if(years > 0) result = Math.round(seconds / (86400.0 * 365.0));
        else if(days > 0) result = Math.round(seconds / 86400.0);
        else if(hours > 0) result = Math.round(seconds / 3600.0);
        else if(minutes > 0) result = Math.round(seconds / 60.0);
        else result = seconds;

        if(years > 0) postfix = " year";
        else if(days > 0) postfix = " day";
        else if(hours > 0) postfix = " hour";
        else if(minutes > 0) postfix = " minute";
        else postfix = " second";

        return result + postfix + ((result != 1) ? "s" : "");
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top