Comment puis-je calculer un laps de temps en Java et formater la sortie?

Je veux prendre deux fois (en secondes depuis l'époque) et montrer la différence entre les deux dans des formats comme:

  • 2 minutes
  • 1 heure, 15 minutes
  • 3 heures, 9 minutes
  • Il y a 1 minute
  • Il y a 1 heure, 2 minutes

Comment puis-je accomplir cela??

39
demandé sur Jeremy Logan 2009-03-11 22:11:09

17 réponses

puisque tout le monde crie " YOODAA!!!"mais personne ne publie un exemple concret, voici ma contribution.

Vous pouvez également le faire avec Joda-Time . Utilisation Period pour représenter une période. Pour formater la période souhaitée dans la représentation humaine, l'utilisation PeriodFormatter lequel vous pouvez construire par PeriodFormatterBuilder.

Voici un exemple de coup d'envoi:

DateTime myBirthDate = new DateTime(1978, 3, 26, 12, 35, 0, 0);
DateTime now = new DateTime();
Period period = new Period(myBirthDate, now);

PeriodFormatter formatter = new PeriodFormatterBuilder()
    .appendYears().appendSuffix(" year, ", " years, ")
    .appendMonths().appendSuffix(" month, ", " months, ")
    .appendWeeks().appendSuffix(" week, ", " weeks, ")
    .appendDays().appendSuffix(" day, ", " days, ")
    .appendHours().appendSuffix(" hour, ", " hours, ")
    .appendMinutes().appendSuffix(" minute, ", " minutes, ")
    .appendSeconds().appendSuffix(" second", " seconds")
    .printZeroNever()
    .toFormatter();

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

Beaucoup plus clair et concis, n'est-ce pas?

Cela imprime maintenant

32 years, 1 month, 1 week, 5 days, 6 hours, 56 minutes, 24 seconds ago

(de la Toux, de vieux, de la toux)

64
répondu BalusC 2015-10-25 18:15:55
    Date start = new Date(1167627600000L); // JANUARY_1_2007
    Date end = new Date(1175400000000L); // APRIL_1_2007


    long diffInSeconds = (end.getTime() - start.getTime()) / 1000;

    long diff[] = new long[] { 0, 0, 0, 0 };
    /* sec */diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds);
    /* min */diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds;
    /* hours */diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds;
    /* days */diff[0] = (diffInSeconds = (diffInSeconds / 24));

    System.out.println(String.format(
        "%d day%s, %d hour%s, %d minute%s, %d second%s ago",
        diff[0],
        diff[0] > 1 ? "s" : "",
        diff[1],
        diff[1] > 1 ? "s" : "",
        diff[2],
        diff[2] > 1 ? "s" : "",
        diff[3],
        diff[3] > 1 ? "s" : ""));
42
répondu Timour 2009-03-11 20:39:14

Yup a réveillé les morts que j'ai, Mais voici mon implémentation améliorée basée sur le code posté par @mtim, car ce fil vient presque au-dessus des recherches, donc je joue avec le Sleepy hollow,

    public static String getFriendlyTime(Date dateTime) {
    StringBuffer sb = new StringBuffer();
    Date current = Calendar.getInstance().getTime();
    long diffInSeconds = (current.getTime() - dateTime.getTime()) / 1000;

    /*long diff[] = new long[]{0, 0, 0, 0};
    /* sec *  diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds);
    /* min *  diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds;
    /* hours *  diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds;
    /* days * diff[0] = (diffInSeconds = (diffInSeconds / 24));
     */
    long sec = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds);
    long min = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds;
    long hrs = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds;
    long days = (diffInSeconds = (diffInSeconds / 24)) >= 30 ? diffInSeconds % 30 : diffInSeconds;
    long months = (diffInSeconds = (diffInSeconds / 30)) >= 12 ? diffInSeconds % 12 : diffInSeconds;
    long years = (diffInSeconds = (diffInSeconds / 12));

    if (years > 0) {
        if (years == 1) {
            sb.append("a year");
        } else {
            sb.append(years + " years");
        }
        if (years <= 6 && months > 0) {
            if (months == 1) {
                sb.append(" and a month");
            } else {
                sb.append(" and " + months + " months");
            }
        }
    } else if (months > 0) {
        if (months == 1) {
            sb.append("a month");
        } else {
            sb.append(months + " months");
        }
        if (months <= 6 && days > 0) {
            if (days == 1) {
                sb.append(" and a day");
            } else {
                sb.append(" and " + days + " days");
            }
        }
    } else if (days > 0) {
        if (days == 1) {
            sb.append("a day");
        } else {
            sb.append(days + " days");
        }
        if (days <= 3 && hrs > 0) {
            if (hrs == 1) {
                sb.append(" and an hour");
            } else {
                sb.append(" and " + hrs + " hours");
            }
        }
    } else if (hrs > 0) {
        if (hrs == 1) {
            sb.append("an hour");
        } else {
            sb.append(hrs + " hours");
        }
        if (min > 1) {
            sb.append(" and " + min + " minutes");
        }
    } else if (min > 0) {
        if (min == 1) {
            sb.append("a minute");
        } else {
            sb.append(min + " minutes");
        }
        if (sec > 1) {
            sb.append(" and " + sec + " seconds");
        }
    } else {
        if (sec <= 1) {
            sb.append("about a second");
        } else {
            sb.append("about " + sec + " seconds");
        }
    }

    sb.append(" ago");


    /*String result = new String(String.format(
    "%d day%s, %d hour%s, %d minute%s, %d second%s ago",
    diff[0],
    diff[0] > 1 ? "s" : "",
    diff[1],
    diff[1] > 1 ? "s" : "",
    diff[2],
    diff[2] > 1 ? "s" : "",
    diff[3],
    diff[3] > 1 ? "s" : ""));*/
    return sb.toString();
}

, Il peut évidemment être amélioré. fondamentalement, il essaie d'obtenir la période de temps plus amicale, il y a quelques limitations, c'est-à-dire qu'il se comporterait étrangement si le temps passé (paramètre) est à l'avenir, et son limité jusqu'aux jours, heures et secondes seulement (mois et années non traitées, donc que quelqu'un d'autre ;-).

Les exemples de sorties sont:

  • Il y a environ une seconde
  • il y a 8 minutes et 34 secondes
  • Il y a une heure et 4 minutes
  • Il y a un jour
  • il y a 29 jours
  • Il y a un an et 3 mois

, cheers: D

EDIT: supporte maintenant les mois et les années: p

16
répondu Abduliam Rehmanius 2010-05-09 01:05:46

Je vous recommande de jeter un oeil à HumanTime

11
répondu Peter Lindholm 2009-03-11 19:30:51

Évitez les classes date-heure héritées

Les autres réponses peuvent être correctes mais sont obsolètes. Les anciennes classes date-heure gênantes en Java sont maintenant héritées, supplantées par java.les classes de temps.

De même, le projetJoda-Time , maintenant en mode de maintenance , conseille la migration vers le java .temps classes.

Utilisation de java.temps

Instant

Deux fois (en secondes depuis l'époque)

En java.le temps, nous représenter les moments sur la timeline en UTC comme Instant. Je suppose que votre époque est la même que celle de java.temps, le premier moment de 1970 en UTC (1970-01-01T00:00:00Z). Notez qu'un Instant a une résolution de nanosecondes. Une méthode d'usine de commodité construit un Instant à partir de secondes entières, comme demandé dans la Question.

Instant start = Instant.ofEpochSecond( … );
Instant stop = Instant.ofEpochSecond( … );

Ici, nous utilisons le moment actuel et quelques minutes plus tard.

Instant start = Instant.now() ;
Instant stop = start.plusSeconds( TimeUnit.MINUTES.toSeconds( 7L ) ) ;  // Seven minutes as a number of seconds.

Duration

En java.temps, une période de temps non attachée à la timeline est représentée en deux façon. Pour les années-mois-jours, nous avons Period. Pour les heures-minutes-secondes, nous avons Duration.

Duration duration = Duration.between( start , stop );

Demi-Ouvert

Le temps écoulé est calculé avec L'approche semi-ouverte. Dans cette approche, le début est inclusive, tandis que la fin est exclusive. Cette approche est couramment utilisée dans le travail date-heure. Je crois que l'utilisation de cette approche de manière cohérente dans votre base de code aidera à éliminer les erreurs et les malentendus dus aux ambiguïtés, et facilitera le charge cognitive de votre programmation.

ISO 8601

La norme ISO 8601 définit de nombreux formats pratiques pour représenter les valeurs date-heure sous forme de texte. Ces formats sont conçus pour éviter toute ambiguïté, être faciles à analyser par machine et être intuitifs à lire par les humains à travers les cultures.

Le java.les classes de temps utilisent ces formats par défaut lors de l'analyse et de la génération de chaînes.

Pour un laps de temps non attaché à la timeline, la norme définit un format de PnYnMnDTnHnMnSP marque le début et T sépare les années-mois-jours de toutes les heures-minutes-secondes. Donc, une heure et demie est PT1H30M.

Dans notre exemple de code en utilisant sept minutes:

String outputStandard = duration.toString();

PT7M

Voir l'exemple ci-dessus code en cours d'exécution en direct à IdeOne.com .

Je suggère de coller avec ces formats autant que possible, certainement lors de l'échange ou de la sérialisation des données date-heure, mais aussi envisager d'utiliser dans un interface utilisateur le cas échéant et vos utilisateurs peuvent être formés pour les utiliser.

Je recommande jamais en utilisant le format horloge-heure (ex: 01:30 pour une heure et demie) car ce format est complètement ambigu avec une heure de la journée.

Récupération de pièces pour construire une chaîne

Si vous devez préciser la période de temps comme on le voit dans la Question, vous devrez construire le texte vous-même.

  • Pour Period, appel getYears, getMonths, et getDays pour récupérer chaque partie.
  • Curieusement, la Duration classe n'avaient pas ces accesseurs dans Java 8, mais acquise dans Java 9 et plus tard: toDaysPart, toHoursPart, toMinutesPart, toSecondsPart, et toNanosPart.

Un exemple de code, simple et basique pour vous aider à démarrer.

int days = duration.toDaysPart() ;
int hours = duration.toHoursPart() ;
int minutes = duration.toMinutesPart() ;
int seconds = duration.toSecondsPart() ;
int nanos = duration.toNanosPart() ;

StringBuilder sb = new StringBuilder( 100 );

if( days != 0 ) { 
    sb.append( days + " days" ) ;
};

if( hours != 0 ) { 
    sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ;  // Append comma if any existing text.
    sb.append( hours + " hours" ) ;
};

if( minutes != 0 ) { 
    sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ;  // Append comma if any existing text.
    sb.append( minutes + " minutes" ) ;
};

if( seconds != 0 ) { 
    sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ;  // Append comma if any existing text.
    sb.append( seconds + " seconds" ) ;
};

if( nanos != 0 ) { 
    sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ;  // Append comma if any existing text.
    sb.append( nanos + " nanos" ) ;
};

String output = sb.toString();

Ou peut-être pourriez-vous écrire du code slicker en utilisant DateTimeFormatterBuilder d'une manière montrée avec Joda-Time dans la réponse de Balus C.


À propos Java.temps

Le java.le framework time est intégré à Java 8 et versions ultérieures. Ces classes permettent d'éviter la pénible vieux héritage date-heure classes telles que java.util.Date, Calendar, & SimpleDateFormat.

Le projetJoda-Time , maintenant en mode de maintenance , conseille la migration vers le java .temps classes.

Pour en savoir plus, consultez le tutoriel Oracle. Et débordement de pile de recherche pour de nombreux exemples et des explications. La spécification est JSR 310 .

Où obtenir le java.les classes de temps?

Le ThreeTen-Extra Projet étend java.temps avec des classes supplémentaires. Ce projet est un terrain d'essai pour les futurs ajouts possibles à java.temps. Vous pouvez trouver quelques classes utiles ici comme Interval, YearWeek, YearQuarter, andfz plus.

8
répondu Basil Bourque 2017-05-23 10:31:37

Je ne suis pas un expert en Java, mais vous pouvez faire t1-t2=t3 (en secondes) puis diviser cela par 60, vous donnerait des minutes, par un autre 60 vous donnerait des secondes. Ensuite, il est juste une question de déterminer combien de divisions vous avez besoin.

J'espère que ça aide.

1
répondu TuxMeister 2009-03-11 19:15:04

Si vos plages horaires dépassent les limites de l'heure d'été, voulez-vous indiquer le nombre de jours?

Par exemple, 23:00 à 23:00 le lendemain est toujours un jour, mais peut être 23, 24 ou 25 heures selon que vous traversez une transition d'heure d'été.

Si vous vous souciez de cela, assurez-vous de le prendre en compte dans votre choix.

1
répondu Adrian Pronk 2009-03-11 23:17:50

Du code qui joue avec le formatage de date... et il y a le temps.

SimpleDateFormat curFormater = new SimpleDateFormat("EEE, dd MMM yyyy kk:mm:ss"); 
    try {
        Date dateObj = curFormater.parse(pubDate);

        SimpleDateFormat postFormater = new SimpleDateFormat("MMMM dd, yyyy ss:mm:hh");              
        String newDateStr = postFormater.format(dateObj); 
        Log.v("THE NEW DATE IS",newDateStr);            
        long pubdateinmilis = dateObj.getTime();            
        pubDate = (String) DateUtils.getRelativeTimeSpanString(pubdateinmilis, System.currentTimeMillis(),DateUtils.HOUR_IN_MILLIS,DateUtils.FORMAT_ABBREV_RELATIVE);

    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
1
répondu OWADVL 2012-04-19 09:30:12

Je commence toujours par Joda Time . Travailler avec des dates et des heures en Java est toujours "amusant", mais le temps Joda prend la souche au large.

Ils ont des classes D'intervalle et de durée qui font la moitié de ce que vous cherchez. Je ne sais pas s'ils ont une fonction pour sortir en format lisible. Je vais continuer à chercher.

HTH

0
répondu mr_urf 2009-03-11 19:18:32

La classe Calendar peut gérer la plupart des mathématiques liées à la date. Vous devrez obtenir le résultat de compareTo et sortir le format vous-même. Il n'y a pas une bibliothèque standard qui fait exactement ce que vous cherchez, bien qu'il puisse y avoir une bibliothèque tierce qui le fait.

0
répondu Ben S 2009-03-11 19:18:49

OK, après une brève lecture de L'API, il semble que vous pourriez faire ce qui suit: -

  1. Créez des ReadableInstants représentant l'Heure de début et l'Heure de fin.
  2. Heures D'Utilisation.hoursBetween pour obtenir le nombre d'heures
  3. Utilisez Minutes.minutesBetween pour obtenir le nombre de minutes
  4. Utilisez le mod 60 sur les minutes pour obtenir les minutes restantes
  5. et voilà!

HTH

0
répondu mr_urf 2009-03-11 19:31:29

La solution de "Abduliam Rehmanius" semble assez agréable, ou vous pouvez utiliser une bibliothèque ci-dessus ou vous pouvez créer de nouvelles choses simples, référez-vous à la solution js ici: http://www.datejs.com/. Il n'est pas difficile de se transformer en Java lang: -)

J'espère que mon lien vous sera utile!

0
répondu Tam Vo 2011-09-03 03:51:02

Le formatage des intervalles de temps en java apparaît fréquemment dans les pulls ETL ou DB. L'extrait de code suivant est la façon dont j'obtiens le pouls de l'opération.

    SimpleDateFormat ymdhms=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    DecimalFormat formatter = new DecimalFormat("#,###"); /* ("#,###.00"); gives you the decimal fractions */
    int counter=0;
    Date beginTime0=new Date();
    while (<some end condition>) {

        <some time consuming operation>

        /*// uncomment this section durring initial exploration of the time consumer
        if(counter>100000){
            System.out.println("debug exiting due to counter="+counter);
            System.exit(0);
        }
        */

        if(0==counter%1000){
            Date now = new Date();
            long diffInSeconds = (now.getTime() - beginTime0.getTime()) / 1000;
            long diff[] = new long[] { 0, 0, 0, 0 };
            diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds);                        /* sec   */ 
            diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds; /* min   */ 
            diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds; /* hours */ 
            diff[0] = (diffInSeconds = (diffInSeconds / 24));                                            /* days  */ 
            String delta = String.format(
                "%s%s%s%s"
                ,(diff[0]>0?String.format("%d day%s "    ,diff[0],(diff[0]!=1?"s":"")):"")
                ,(diff[1]>0?String.format("%2d hour%s "  ,diff[1],(diff[1]!=1?"s":" ")):"")
                ,(diff[2]>0?String.format("%2d minute%s ",diff[2],(diff[2]!=1?"s":" ")):"")
                ,           String.format("%2d second%s ",diff[3],(diff[3]!=1?"s":" "))
            );
            System.out.println(String.format(
                "%12s %s delta= %s"
                ,formatter.format(counter)
                ,ymdhms.format(new Date())
                ,delta
                )
            );
        }
        counter++;
    }
0
répondu teserecter 2014-02-05 20:12:23

Je pense que vous cherchez quelque chose comme PrettyTime
PrettyTime est une bibliothèque de formatage de temps OpenSource. Entièrement personnalisable, il crée lisible par l'homme, horodatages relatifs comme ceux vus sur Digg, Twitter et Facebook.Son disponible dans plus de 30 langues!
lien: https://github.com/ocpsoft/prettytime

Peut être utilisé dans android aussi

Par exemple

System.out.println(p.format(new Date(System.currentTimeMillis() + 1000*60*10)));
        //prints: "10 minutes from now"
0
répondu Habel Philip 2016-08-26 10:16:26

Récemment, j'ai eu la même exigence où j'ai besoin d'une méthode de base pour imprimer la durée. Je n'avais pas la possibilité d'utiliser une bibliothèque tierce. Donc, je viens de peaufiner l'idée de @mtim plus loin.

public static void main(String[] args) throws IOException, ParseException {
        String since = "2017-02-24T04:44:05.601Z";
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        TimeZone utc = TimeZone.getTimeZone("UTC");
        dateFormat.setTimeZone(utc);

        Date sinceDate = dateFormat.parse(since);
        Date now = new Date();
        long durationInSeconds  = TimeUnit.MILLISECONDS.toSeconds(now.getTime() - sinceDate.getTime());

        long SECONDS_IN_A_MINUTE = 60;
        long MINUTES_IN_AN_HOUR = 60;
        long HOURS_IN_A_DAY = 24;
        long DAYS_IN_A_MONTH = 30;
        long MONTHS_IN_A_YEAR = 12;

        long sec = (durationInSeconds >= SECONDS_IN_A_MINUTE) ? durationInSeconds % SECONDS_IN_A_MINUTE : durationInSeconds;
        long min = (durationInSeconds /= SECONDS_IN_A_MINUTE) >= MINUTES_IN_AN_HOUR ? durationInSeconds%MINUTES_IN_AN_HOUR : durationInSeconds;
        long hrs = (durationInSeconds /= MINUTES_IN_AN_HOUR) >= HOURS_IN_A_DAY ? durationInSeconds % HOURS_IN_A_DAY : durationInSeconds;
        long days = (durationInSeconds /= HOURS_IN_A_DAY) >= DAYS_IN_A_MONTH ? durationInSeconds % DAYS_IN_A_MONTH : durationInSeconds;
        long months = (durationInSeconds /=DAYS_IN_A_MONTH) >= MONTHS_IN_A_YEAR ? durationInSeconds % MONTHS_IN_A_YEAR : durationInSeconds;
        long years = (durationInSeconds /= MONTHS_IN_A_YEAR);

        String duration = getDuration(sec,min,hrs,days,months,years);
        System.out.println(duration);
    }
    private static String getDuration(long secs, long mins, long hrs, long days, long months, long years) {
        StringBuffer sb = new StringBuffer();
        String EMPTY_STRING = "";
        sb.append(years > 0 ? years + (years > 1 ? " years " : " year "): EMPTY_STRING);
        sb.append(months > 0 ? months + (months > 1 ? " months " : " month "): EMPTY_STRING);
        sb.append(days > 0 ? days + (days > 1 ? " days " : " day "): EMPTY_STRING);
        sb.append(hrs > 0 ? hrs + (hrs > 1 ? " hours " : " hour "): EMPTY_STRING);
        sb.append(mins > 0 ? mins + (mins > 1 ? " mins " : " min "): EMPTY_STRING);
        sb.append(secs > 0 ? secs + (secs > 1 ? " secs " : " secs "): EMPTY_STRING);
        sb.append("ago");
        return sb.toString();
    }

La sortie sera un intervalle de temps (durée) imprimé en mots, par exemple 1 day 2 hours 51 mins 41 secs ago

0
répondu i_am_zero 2017-02-25 07:37:47

Cette question est ancienne et a déjà une réponse, mais j'ai une meilleure solution. Utiliser relativeSpan from date utils

                dateHere.setText(DateUtils.getRelativeTimeSpanString(timeInMillis,
                        System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS));

, Il prend comme arguments: longue/int temps, le temps actuel et comment vous le voulez, _month,minute,deuxième, etc

0
répondu Lucem 2017-10-29 08:38:03
long time1, time2;
time1 = System.currentMillis();

.. drink coffee

time2 = System.currentMillis();

long difference = time2 - time1 // millies between time1 and time2

java.util.Date differneceDate = new Date(difference);

Pour créer une chaîne comme "2 Minutes", vous devez utiliser DateFormatter / DateFormat. Vous pouvez trouver plus de détails à ce sujet dans la spécification de L'API Java (java.sun.com).

-2
répondu Timo 2009-03-11 19:22:23