Je veux prendre deux fois (en secondes depuis Epoch) et montrer la différence entre les deux dans des formats comme:
Comment puis-je accomplir cela??
Depuis que tout le monde crie "YOODAA !!!" mais personne ne poste un exemple concret, voici ma contribution.
Vous pouvez également le faire avec Joda-Time . Utilisez Period
pour représenter une période. Pour formater la période dans la représentation humaine souhaitée, utilisez PeriodFormatter
que vous pouvez construire avec 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
Il y a 32 ans, 1 mois, 1 semaine, 5 jours, 6 heures, 56 minutes, 24 secondes
(Toux, vieux, toux)
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" : ""));
Yup a réveillé les morts que j'ai, mais voici mon implémentation améliorée basée sur le code posté de @mtim, car ce fil vient presque au-dessus des recherches, donc je m'amuse avec le creux assoupi,
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();
}
Cela peut évidemment être amélioré. fondamentalement, il essaie de rendre le laps de temps plus convivial, il y a quelques limitations cependant, c’est-à-dire qu’il se comporterait étrangement si le temps passé (paramètre) était à l’avenir, et limité aux jours, heures et secondes manipulé, pour que quelqu'un d'autre puisse ;-).
les exemples de résultats sont:
, acclamations: D
EDIT: supporte maintenant les mois et les années: P
Je vous recommande de regarder HumanTime
Les autres réponses peuvent être correctes mais sont obsolètes. Les anciennes classes de date-heure problématiques en Java sont désormais héritées, supplantées par les classes Java.time.
De même, le projet Joda-Time , désormais en mode { maintenance) , conseille de migrer vers les classes Java.time .
Instant
deux fois (en secondes depuis Epoch)
En Java.time, nous représentons des moments sur la ligne de temps en UTC sous la forme Instant
. Je suppose que votre époque est la même que celle de Java.time, le premier moment de 1970 en UTC (1970-01-01T00:00:00Z
). Notez qu'une Instant
a une résolution de nanosecondes. Une méthode de fabrique de commodité construit une Instant
à partir de secondes entières, comme indiqué 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
Dans Java.time, un intervalle de temps non attaché à la timeline est représenté de deux manières. Pour années-mois-jours, nous avons Period
. Pour heures-minutes-secondes, nous avons Duration
.
Duration duration = Duration.between( start , stop );
Le temps écoulé est calculé avec l'approche Half-Open. Dans cette approche, le début est inclusif tandis que la fin est exclusif. Cette approche est couramment utilisée dans le travail date-heure. Je crois que l’utilisation systématique de cette approche dans l’ensemble de votre code contribuera à éliminer les erreurs et les incompréhensions dues aux ambiguïtés et à alléger la charge cognitive de votre programmation.
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 les ambiguïtés, être faciles à analyser par une machine et intuitifs à lire par des humains de différentes cultures.
Les classes Java.time utilisent ces formats par défaut lors de l'analyse et de la génération de chaînes.
Pendant un laps de temps non lié à la chronologie, le norme définit un format de PnYnMnDTnHnMnS
où P
marque le début et T
sépare les années-mois-jours des heures-minutes-secondes. Donc, une heure et demie est PT1H30M
.
Dans notre exemple de code utilisant sept minutes:
String outputStandard = duration.toString();
PT7M
Voir l'exemple ci-dessus code exécuté en direct sur IdeOne.com .
Je suggère de conserver ces formats autant que possible, certainement lors de l'échange ou de la sérialisation des données date-heure, mais envisagez également d'utiliser une interface utilisateur, le cas échéant, afin que vos utilisateurs puissent être formés à leur utilisation.
Je recommande jamais en utilisant le format d'horloge (ex: 01:30 pour une heure et demie) car ce format est complètement ambigu avec l'heure.
Si vous devez préciser le laps de temps indiqué dans la question, vous devrez créer le texte vous-même.
Period
, appelez getYears
, getMonths
et getDays
pour récupérer chaque partie. Duration
n'avait pas de tels accesseurs dans Java 8 , mais les gagnait dans Java 9 et plus tard: toDaysPart
, toHoursPart
, toMinutesPart
, toSecondsPart
et toNanosPart
. Quelques exemples de code, simples et basiques 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 plus lisse en utilisant DateTimeFormatterBuilder
de la même manière que Joda-Time dans la réponse de Balus C .
Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes gênantes héritées _ date-heure telles que Java.util.Date
, Calendar
_, & SimpleDateFormat
.
Le projet Joda-Time , désormais en mode maintenance , conseille de migrer vers les classes Java.time .
Pour en savoir plus, consultez le Tutoriel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .
Où obtenir les classes Java.time?
Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts à Java.time. Vous pouvez y trouver des classes utiles telles que Interval
_, YearWeek
, YearQuarter
_, andfz plus _.
Je ne suis pas un expert en Java, mais vous pouvez faire t1-t2 = t3 (en secondes), puis diviser par 60, vous donnerait des minutes, par 60 autres, vous donnerait des secondes. Ensuite, il suffit de déterminer le nombre de divisions nécessaires.
J'espère que ça aide.
Si votre plage horaire dépasse les limites de l'heure d'été, souhaitez-vous indiquer le nombre de jours?
Par exemple, le lendemain, de 23h00 à 23h00 est toujours un jour, mais il peut durer 23, 24 ou 25 heures, selon que vous traversiez ou non une transition heure avancée.
Si cela vous tient à cœur, assurez-vous de le prendre en compte dans votre choix.
un 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();
}
Cette question est ancienne et a déjà une réponse mais j'ai une meilleure solution . Utilisez relativeSpan à partir de date utils
dateHere.setText(DateUtils.getRelativeTimeSpanString(timeInMillis,
System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS));
il faut des arguments: long/int time, heure actuelle et comment vous le voulez, _month, minute, seconde, etc.
Je commence toujours par Joda Time . Travailler avec des dates et des heures en Java est toujours "amusant", mais Joda Time vous facilite la tâche.
Ils ont des classes d'intervalle et de durée qui font la moitié de ce que vous recherchez. Je ne sais pas si elles ont une fonction permettant d’afficher dans un format lisible. Je vais continuer à chercher.
HTH
Récemment, j'ai eu la même exigence, où il me fallait une méthode de base pour imprimer la durée. Je n'avais pas la possibilité d'utiliser une bibliothèque tierce. Je viens donc de préciser l’idée de @mtim.
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é avec des mots, par exemple, .1 day 2 hours 51 mins 41 secs ago
OK, après une brève lecture de l'API, il semble que vous puissiez faire ce qui suit: -
HTH
La solution de "Abduliam Rehmanius" semble assez jolie, vous pouvez en utiliser une autre ou créer de nouvelles choses simples, consultez la solution JS à l'adresse suivante: http://www.datejs.com/ . Il n'est pas difficile de transformer en langage Java :-)
J'espère que mon lien vous sera utile!
Les durées de formatage dans Java me sont fréquentes dans les extractions ETL ou DB. L'extrait de code suivant explique comment obtenir l'impulsion 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++;
}
Je pense que vous cherchez quelque chose comme PrettyTime
PrettyTime est une bibliothèque de formatage d’heure OpenSource. Entièrement personnalisable, il crée lisible par l'homme _, _ {horodatage relatif comme ceux que l'on voit sur Digg, Twitter et Facebook.
link: 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"