J'ai...
Date start = new Date()
...
...
...
Date stop = new Date()
J'aimerais avoir les années, les mois, les jours, les heures, les minutes et les secondes écoulés entre ces deux dates.
-
Je vais préciser la question.
Je veux juste obtenir le temps écoulé, en tant que mesure absolue, sans tenir compte des années bissextiles, des jours de chaque mois, etc.
Ainsi, je pense qu'il est impossible de connaître les années et les mois écoulés. Tout ce que je peux obtenir, ce sont des jours, des heures, des minutes et des secondes.
Plus précisément, je veux dire qu’une tâche a duré, par exemple.
20 sec
13 min, 4 sec
2 h, 10 min, 2 sec
4 d, 4 h, 2 min, 2 sec
Alors s'il vous plaît pardonnez mon manque de précision.
Je viens de découvrir cette solution rapide basée sur Groovy:
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;
Cela devrait vous donner toutes les informations que vous avez demandées.
EDIT: Puisque les gens semblent confus, non, cela ne prend pas en compte des choses telles que les années bissextiles ou les changements d’heure. C’est purement passé time , c’est ce que demande openas.
Pas si facile avec l'API Date standard.
Vous voudrez peut-être regarder 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 commencer; merci au répondant qui l’a suggéré. Voici une version plus condensée du code Joda suggérée:
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());
(Je ne sais pas si cela aide la question initiale mais certainement les chercheurs).
Duration.between( then , Instant.now() )
La méthode moderne utilise les classes Java.time qui supplantent les anciennes classes gênantes de date et d’heure.
Au lieu de Date
, utilisez Instant
. La classe Instant
représente un moment sur la ligne temporelle en UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale).
Instant then = Instant.now();
…
Instant now = Instant.now();
Utilisez la classe Duration
pendant un laps de temps non lié à la chronologie, avec une résolution jour-heures-minutes-secondes-nanos.
Duration d = Duration.between( then , now );
Pendant un laps de temps avec une résolution années-mois-jours, utilisez la classe Period
.
La génération d'une chaîne est conforme à la norme ISO 8601 format pour les durées : PnYnMnDTnHnMnS
. La P
marque le début. La T
sépare les années, les mois, les jours et les heures, les minutes, les secondes. Donc, deux heures et demie, c'est PT2H30M
.
String output = d.toString();
Dans Java 9 et versions ultérieures, vous pouvez accéder aux différentes pièces à l'aide des méthodes toDaysPart
, toHoursPart
, etc.
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
_ et plus _.
Depuis Java 1.5, vous devriez utiliser TimeUnit.
Voici un exemple simple et clair pour cela. Je pense qu'en groovy, il pourrait être 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 les retours multiples s'il vous plaît;)
En fait, en ce qui concerne les réponses ci-dessus à propos de Joda-Time .
Il existe un moyen plus simple de procéder avec Joda-Time’s Period class:
Period period = new Period(startDate, endDate);
System.out.println(PeriodFormat.getDefault().print(period));
Pour personnaliser la sortie, consultez les classes PeriodFormat , PeriodFormatter et PeriodFormatterBuilder .
Mis à part l'excellent JodaTime API mentionné ci-dessus que je fais recommande, la meilleure alternative Java standard que vous pouvez avoir est le Java.util.Calendar
. Il est fastidieux de travailler avec cela (c'est un euphémisme .. regardez les exemples JodaTime sur une seule ligne ici), mais vous pouvez aussi calculer le temps écoulé. La clé importante est que vous devez utiliser Calendar#add()
dans une boucle pour obtenir la valeur écoulée pour les années, les mois et les jours et prendre en compte les jours bissextiles, les années et les siècles. Vous ne devriez pas les calculer à partir des (millièmes) 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 imprimer mon âge dès maintenant =)
Oh, je devrais ajouter, vous pouvez "convertir" Date
en Calendar
en utilisant Calendar#setTime()
.
Hmm, si je comprends ce que vous demandez, vous voulez savoir que si:
début = le 1 janvier 2001 à 10h00 et 00h00
arrêt = le 6 janvier 2003 à 12 h 01 min.
vous voulez une réponse de 2 ans, 0 mois, 5 jours, 2 heures, 1 minute
Malheureusement, cette réponse est spécieuse. Et si les dates étaient le 2 janvier et le 31 janvier? Serait-ce 29 jours? Ok, mais du 2 février au 2 mars est de 28 (29) jours, mais serait indiqué comme 1 mois?
La durée, autre que quelques secondes ou éventuellement plusieurs jours, est variable sans connaître le contexte puisque les mois et les années ont des durées différentes. La différence entre 2 dates doit être exprimée en unités statiques, facilement calculables à partir de stop.getTime () - start.getTime () (qui correspond à la différence en millisecs).
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);
}
résultats:
10.11.2010 00:08:12 ImportData main INFO: [début] 2010-11-10 00: 08: 10.306 10.11.2010 00:08:12 ImportData main INFO: [ fin] 2010-11-10 00: 08: 12.318 10.11.2010 00:08:12 ImportData main INFO: [durée] 00: 00: 02.012
C’est une autre fonction similaire, elle n’affichera pas les jours, heures, minutes, etc. si elle n’est pas nécessaire, changez ses littéraux 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;
}
}
C’est une fonction complète que j’ai implémentée à partir de Sebastian Celis answer. Et encore une fois, de son poste - cela ne prend pas en compte des choses telles que les années bissextiles ou les commutations d’heures d’été. C'est pur le temps écoulé.
La sortie est adaptée à mes besoins. Cela ne produit que trois sections significatives. Au lieu de revenir
4 mois, 2 semaines, 3 jours, 7 heures, 28 minutes, 43 secondes
Il retourne juste les 3 premiers blocs (voir plus d’échantillons à la fin du 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 de déclaration de test:
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 ne sert à rien de créer un objet Date car il ne fait qu'emballer System.currentTimeMillis (). La fonction getTime () ouvre simplement l'objet Date. Je vous suggère simplement d'utiliser cette fonction pour obtenir un long.
Si vous avez seulement besoin d'une seconde précision, c'est très bien. Cependant, si vous voulez une précision inférieure à une milliseconde, utilisez System.nanoTime () pour obtenir le temps écoulé.