Calculer le temps écoulé En Java / Groovy
j'ai...
Date start = new Date()
...
...
...
Date stop = new Date()
j'aimerais avoir les années, mois, jours, heures, minutes et secondes ellapsed entre ces deux dates.
--
je vais affiner la question.
je veux juste obtenir le temps écoulé, comme mesure absolue, c'est-à-dire sans tenir compte des années bissextiles, des jours de chaque mois, etc.
donc je pense qu'il est impossible d'obtenir les années et des mois se sont écoulés, tout ce que je peux avoir c'est des jours, des heures, des minutes et des secondes.
plus précisément, je veux dire qu'une certaine tâche a duré pour par exemple
20 sec
13 min, 4 sec
2 h, 10 min, 2 sec
4 d, 4 h, 2 min, 2 sec
alors pardonnez mon manque de précision.
14 réponses
je viens de découvrir cette solution rapide et originale:
import groovy.time.TimeCategory
import groovy.time.TimeDuration
TimeDuration td = TimeCategory.minus( stop, start )
println td
vous pouvez faire tout cela avec division et mod.
long l1 = start.getTime();
long l2 = stop.getTime();
long diff = l2 - l1;
long secondInMillis = 1000;
long minuteInMillis = secondInMillis * 60;
long hourInMillis = minuteInMillis * 60;
long dayInMillis = hourInMillis * 24;
long elapsedDays = diff / dayInMillis;
diff = diff % dayInMillis;
long elapsedHours = diff / hourInMillis;
diff = diff % hourInMillis;
long elapsedMinutes = diff / minuteInMillis;
diff = diff % minuteInMillis;
long elapsedSeconds = diff / secondInMillis;
qui devrait vous donner toutes les informations que vous avez demandées.
EDIT: puisque les gens semblent être confus, non, cela ne prend pas des choses comme les années bissextiles ou les commutateurs d'heure d'été en compte. Il est pur écoulé temps , qui est ce que opensas demandé.
pas si facile avec L'API Date standard.
Vous voudrez peut-être chercher à Joda Time , ou JSR 310 à la place.
Je ne suis pas un expert en Joda, mais je pense que le code serait:
Interval interval = new Interval(d1.getTime(), d2.getTime());
Period period = interval.toPeriod();
System.out.printf(
"%d years, %d months, %d days, %d hours, %d minutes, %d seconds%n",
period.getYears(), period.getMonths(), period.getDays(),
period.getHours(), period.getMinutes(), period.getSeconds());
en ce qui concerne JodaTime je viens de le faire démarrer; merci à l'intervenant qui l'a suggéré. Voici une version plus condensée du code Joda suggéré:
Period period = new Period(d1.getTime(), d2.getTime());
System.out.printf(
"%d years, %d months, %d days, %d hours, %d minutes, %d seconds%n",
period.getYears(), period.getMonths(), period.getDays(),
period.getHours(), period.getMinutes(), period.getSeconds());
(pas sûr que cela aide la question originale, mais certainement les chercheurs).
bien depuis Java 1.5 vous devez utiliser TimeUnit.
voici un exemple simple et simple pour cela. Je pense qu'en groovy il pourrait devenir plus court (comme toujours).
/**
* Formats a given {@link Date} to display a since-then timespan.
* @param created
* @return String with a format like "3 minutes ago"
*/
public static String getElapsedTime(Date created) {
long duration = System.currentTimeMillis() - created.getTime();
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration);
long days = TimeUnit.MILLISECONDS.toDays(duration);
long hours = TimeUnit.MILLISECONDS.toHours(duration);
long minutes = TimeUnit.MILLISECONDS.toMinutes(duration);
if (days > 0) {
return days + " days";
}
if (hours > 0) {
return hours + " hrs";
}
if (minutes > 0) {
return minutes + " minutes";
}
return seconds + " seconds";
}
Oh, et éviter de multiples retours s'il vous plaît ;)
en Fait, concernant les réponses ci-dessus à propos de Joda-Time .
il y a une façon plus facile de le faire avec la classe
de Joda-Time période classe:Period period = new Period(startDate, endDate);
System.out.println(PeriodFormat.getDefault().print(period));
pour personnaliser la sortie, regardez dans les PeriodFormat , PeriodFormatter , et PeriodFormatterBuilder classes.
tl; dr
Duration.between( then , Instant.now() )
utilisant java.time
d'une façon moderne utilise le java.les classes de temps qui remplacent les vieilles classes de date ennuyeuses.
au lieu de Date
, utilisez Instant
. La classe Instant
représente un moment sur la ligne de temps dans UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une décimale fraction.)
Instant then = Instant.now();
…
Instant now = Instant.now();
utilisez la classe Duration
pour une période de temps libre de la ligne de temps, avec résolution de jour-Heures-minutes-secondes-nanos.
Duration d = Duration.between( then , now );
pour une période de temps avec la résolution des années-mois-jours, utilisez la classe Period
".
Générer une chaîne de caractères est la norme ISO 8601 format pour les durées : PnYnMnDTnHnMnS
. Le P
marque le début. Le T
sépare les années-mois-jours des heures-minutes-secondes. Donc, deux heures et demie est PT2H30M
.
String output = d.toString();
en Java 9 et plus tard, vous pouvez accéder aux différentes parties avec les méthodes toDaysPart
, toHoursPart
, et ainsi de suite.
à Propos de java.time
Le de java.temps framework est construit dans Java 8 et plus tard. Ces classes remplacent les anciennes héritées classes de date-heure telles que java.util.Date
, Calendar
, & SimpleDateFormat
.
le projet Joda-Time , maintenant en mode maintenance , conseille la migration vers le java.temps classes.
pour en savoir plus, voir le Oracle Tutorial . Et rechercher le débordement de la pile pour de nombreux exemples et explications. La spécification est JSR 310 .
où obtenir le java.les classes de temps?
- Java SE 8 et SE 9 et plus tard
- Built-in.
- fait partie de L'API Java standard avec une implémentation groupée.
- Java 9 ajoute des fonctionnalités mineures et des corrections.
- Java SE 6 et SE 7
- une grande partie de la java.la fonctionnalité time est rétroportée à Java 6 & 7 dans ThreeTen-Backport .
- Android
le projet ThreeTen-Extra étend java.temps avec des cours supplémentaires. Ce projet est un terrain d'expérimentation pour d'éventuelles futures additions à java.temps. Vous pouvez trouver ici quelques cours utiles tels que: Interval
, YearWeek
, YearQuarter
, et plus .
Hmm, si j'obtiens ce que vous demandez, vous voulez savoir que si:
start = 1 Jan, 2001, 10:00:00.000 suis et
stop= Jan 6, 2003, 12: 01:00.000 pm
vous voulez une réponse de 2 ans, 0 mois, 5 jours, 2 heures, 1 minute
malheureusement, c'est une réponse spécieuse. Et si les dates étaient le 2 et le 31 janvier? Serait-ce la 29 jours? Ok, mais du 2 février au 2 Mars est de 28 (29) jours, mais serait listé comme 1 mois?
la durée en secondes ou éventuellement en jours est variable sans connaître le contexte puisque les mois et les années sont de longueurs différentes. La différence entre 2 dates devrait être en unités statiques, qui sont facilement calculables à partir de stop.gettime () - start.getTime () (qui est la différence en millisec)
mis à part le grand JodaTime API que je do recommande, la meilleure alternative Java standard que vous pouvez avoir est le java.util.Calendar
. Il est lourd de travailler avec elle (c'est un euphémisme .. regardez la seule ligne JodaTime exemples ici), mais vous pouvez calculer le temps écoulé. Clé importante est que vous devez utiliser le Calendar#add()
dans une boucle pour obtenez la valeur écoulée pour des années, des mois et des jours pour prendre des jours bissextiles, des années et des siècles en compte. Vous ne devriez pas les calculer à partir des (milli)secondes.
voici un exemple de base:
import java.util.Calendar;
public class Test {
public static void main(String[] args) throws Exception {
Calendar start = Calendar.getInstance();
start.set(1978, 2, 26, 12, 35, 0); // Just an example.
Calendar end = Calendar.getInstance();
Integer[] elapsed = new Integer[6];
Calendar clone = (Calendar) start.clone(); // Otherwise changes are been reflected.
elapsed[0] = elapsed(clone, end, Calendar.YEAR);
clone.add(Calendar.YEAR, elapsed[0]);
elapsed[1] = elapsed(clone, end, Calendar.MONTH);
clone.add(Calendar.MONTH, elapsed[1]);
elapsed[2] = elapsed(clone, end, Calendar.DATE);
clone.add(Calendar.DATE, elapsed[2]);
elapsed[3] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 3600000;
clone.add(Calendar.HOUR, elapsed[3]);
elapsed[4] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 60000;
clone.add(Calendar.MINUTE, elapsed[4]);
elapsed[5] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 1000;
System.out.format("%d years, %d months, %d days, %d hours, %d minutes, %d seconds", elapsed);
}
private static int elapsed(Calendar before, Calendar after, int field) {
Calendar clone = (Calendar) before.clone(); // Otherwise changes are been reflected.
int elapsed = -1;
while (!clone.after(after)) {
clone.add(field, 1);
elapsed++;
}
return elapsed;
}
}
il devrait écrire mon âge à partir de Maintenant =)
Oh, je devrais ajouter, vous pouvez" convertir " Date
en Calendar
en utilisant Calendar#setTime()
.
c'est facile; vous devez définir le bon fuseau horaire
import java.util.TimeZone;
import java.util.logging.Logger;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class ImportData {
private final static Logger log = Logger.getLogger(ImportData.class.getName());
private final static DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS");
private final static DateTimeFormatter dtfh = DateTimeFormat.forPattern("HH:mm:ss.SSS");
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
DateTimeZone.setDefault(DateTimeZone.forID("Europe/Berlin"));
// Quotes connection=Quotes.getInstance();
final long start = System.currentTimeMillis();
// do something here ...
// connection.importTickdata();
Thread.currentThread().sleep(2000);
final long end = System.currentTimeMillis();
log.info("[start] " + dtf.print(start));
log.info("[end] " + dtf.print(end));
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
DateTimeZone.setDefault(DateTimeZone.forID("UTC"));
log.info("[duration] " + dtfh.print(end - start));
// connection.logOff();
// System.exit(0);
}
retourne:
10.11.2010 00:08:12 ImportData main INFO: [start] 2010-11-10 00:08:10.306 10.11.2010 00:08:12 ImportData main INFO: [end] 2010-11-10 00:08:12.318 10.11.2010 00:08:12 ImportData main INFO: [duration] 00:00:02.012
il ne sert à rien de créer un objet Date car tout ce que cela fait est wrap System.currentTimeMillis (). La fonction getTime () déballe simplement l'objet Date. Je vous suggère de simplement utiliser cette fonction pour obtenir une longue.
si vous n'avez besoin que d'une seconde précision, c'est parfait. Cependant, si vous voulez le système de précision sub-milliseconde.nanoTime() pour obtenir l'écoulement du temps.
c'est une fonction complète que j'ai implémentée basée sur Sebastian Celis réponse. Et encore une fois, de son post - cela ne prend pas des choses comme années bissextiles ou commutateurs de l'heure d'été en compte. C'est le temps pur écoulé .
le résultat est adapté à mon besoin. Cela ne produit que trois sections importantes. Au lieu de retourner
4 mois, 2 semaines, 3 jours, 7 heures, 28 minutes, 43 secondes
il retourne juste le premier 3 bloc (voir plus d'essai à la fin de la post) :
4 mois, 2 semaines, 3 jours
voici le code source complet de la méthode:
/**
* Format milliseconds to elapsed time format
*
* @param time difference in milliseconds
* @return Human readable string representation - eg. 2 days, 14 hours, 5 minutes
*/
public static String formatTimeElapsedSinceMillisecond(long milisDiff) {
if(milisDiff<1000){ return "0 second";}
String formattedTime = "";
long secondInMillis = 1000;
long minuteInMillis = secondInMillis * 60;
long hourInMillis = minuteInMillis * 60;
long dayInMillis = hourInMillis * 24;
long weekInMillis = dayInMillis * 7;
long monthInMillis = dayInMillis * 30;
int timeElapsed[] = new int[6];
// Define time units - plural cases are handled inside loop
String timeElapsedText[] = {"second", "minute", "hour", "day", "week", "month"};
timeElapsed[5] = (int) (milisDiff / monthInMillis); // months
milisDiff = milisDiff % monthInMillis;
timeElapsed[4] = (int) (milisDiff / weekInMillis); // weeks
milisDiff = milisDiff % weekInMillis;
timeElapsed[3] = (int) (milisDiff / dayInMillis); // days
milisDiff = milisDiff % dayInMillis;
timeElapsed[2] = (int) (milisDiff / hourInMillis); // hours
milisDiff = milisDiff % hourInMillis;
timeElapsed[1] = (int) (milisDiff / minuteInMillis); // minutes
milisDiff = milisDiff % minuteInMillis;
timeElapsed[0] = (int) (milisDiff / secondInMillis); // seconds
// Only adds 3 significant high valued units
for(int i=(timeElapsed.length-1), j=0; i>=0 && j<3; i--){
// loop from high to low time unit
if(timeElapsed[i] > 0){
formattedTime += ((j>0)? ", " :"")
+ timeElapsed[i]
+ " " + timeElapsedText[i]
+ ( (timeElapsed[i]>1)? "s" : "" );
++j;
}
} // end for - build string
return formattedTime;
} // end of formatTimeElapsedSinceMillisecond utility method
voici un exemple d'énoncé d'essai:
System.out.println(formatTimeElapsedSinceMillisecond(21432424234L));
// Output: 8 months, 1 week, 1 day
System.out.println(formatTimeElapsedSinceMillisecond(87724294L));
// Output: 1 day, 22 minutes, 4 seconds
System.out.println(formatTimeElapsedSinceMillisecond(123434L));
// Output: 2 minutes, 3 seconds
il s'agit d'une autre fonction similaire, elle n'apparaîtra PAS jours, Heures, minutes, etc. si elle n'est pas nécessaire changer ses littérales si nécessaire.
public class ElapsedTime {
public static void main(String args[]) {
long start = System.currentTimeMillis();
start -= (24 * 60 * 60 * 1000 * 2);
start -= (60 * 60 * 1000 * 2);
start -= (60 * 1000 * 3);
start -= (1000 * 55);
start -= 666;
long end = System.currentTimeMillis();
System.out.println(elapsedTime(start, end));
}
public static String elapsedTime(long start, long end) {
String auxRet = "";
long aux = end - start;
long days = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0;
// days
if (aux > 24 * 60 * 60 * 1000) {
days = aux / (24 * 60 * 60 * 1000);
}
aux = aux % (24 * 60 * 60 * 1000);
// hours
if (aux > 60 * 60 * 1000) {
hours = aux / (60 * 60 * 1000);
}
aux = aux % (60 * 60 * 1000);
// minutes
if (aux > 60 * 1000) {
minutes = aux / (60 * 1000);
}
aux = aux % (60 * 1000);
// seconds
if (aux > 1000) {
seconds = aux / (1000);
}
milliseconds = aux % 1000;
if (days > 0) {
auxRet = days + " days ";
}
if (days != 0 || hours > 0) {
auxRet += hours + " hours ";
}
if (days != 0 || hours != 0 || minutes > 0) {
auxRet += minutes + " minutes ";
}
if (days != 0 || hours != 0 || minutes != 0 || seconds > 0) {
auxRet += seconds + " seconds ";
}
auxRet += milliseconds + " milliseconds ";
return auxRet;
}
}
il s'agit d'un problème et un algorithme doit être élaboré pour tenir compte des années bissextiles et du nombre exact de mois et de jours en plus des années. Il est intéressant de constater à quel point il est simple d'utiliser une seule unité de mesure. Par exemple, le nombre total de jours entre deux jours est correct comme revêtue de rappel nombre de jours après le nombre de mois et d'années est calculer dans disons deux décennies.
je travaille actuellement sur ceci pour le fournir à partir de mon implémentation PML, pour exemple, sous la forme de:
unemployed <- date.difference[
From = 2009-07-01,
Till = now,
YEARS, MONTHS, DAYS
]: yyyy-MM-dd
$$-> *unemployed -> date.translate[ YEARS, MONTHS, DAYS ] -> print["Unemployed for:", .]
bien sûr, cela serait également utile et nécessaire pour le calcul exact des taux d'intérêt.