Quelle est la bonne méthode pour, étant donné deux objets Date, comparer la différence entre leur portion d'heure uniquement, en ignorant complètement l'année, le mois et le jour?
C'est tout le contraire de cette question .
UPDATE: Voici le code final pour référence future:
private long differenceBetween(Date currentTime, Date timeToRun)
{
Calendar currentCal = Calendar.getInstance();
currentCal.setTime(currentTime);
Calendar runCal = Calendar.getInstance();
runCal.setTime(timeToRun);
runCal.set(Calendar.DAY_OF_MONTH, currentCal.get(Calendar.DAY_OF_MONTH));
runCal.set(Calendar.MONTH, currentCal.get(Calendar.MONTH));
runCal.set(Calendar.YEAR, currentCal.get(Calendar.YEAR));
return currentCal.getTimeInMillis() - runCal.getTimeInMillis();
}
Utilisez les classes modernes Java.time.
Sachez que la comparaison que vous avez demandée n’a peut-être pas de sens, car une heure donnée peut avoir différentes significations à différentes dates et dans différentes zones.
Duration // Span of time, with resolution of nanoseconds.
.between( // Calculate elapsed time.
LocalTime.now( // Get current time-of-day…
ZoneId.of( "Pacific/Auckland" ) // … as seen in a particular time zone.
) // Returns a `LocalTime` object.
,
myJavaUtilDate // Avoid terrible legacy date-time classes such as `Java.util.Date`.
.toInstant() // Convert from `Java.util.Date` to `Java.time.Instant`, both representing a moment in UTC.
.atZone( // Adjust from UTC to a particular time zone. Same moment, same point on the timeline, different wall-clock time.
ZoneId.of( "Pacific/Auckland" ) // Specify time zone by proper naming in `Continent/Region` format, never 2-4 letter pseudo-zones such as `PST`, `CEST`, `CST`, `IST`, etc.
) // Returns a `ZonedDateTime` object.
.toLocalTime() // Extract the time-of-day without the date and without a time zone.
) // Returns a `Duration` object.
.toMillis() // Calculate entire span-of-time in milliseconds. Beware of data-loss as `Instant` uses a finer resolution the milliseconds, and may carry microseconds or nanoseconds.
Je suggère de faire circuler l'objet Duration
digne de la police et ne nécessitant pas d'explication, plutôt qu'un simple nombre entier de millisecondes.
L’approche moderne utilise les classes Java.time qui supplantent les terribles classes héritées telles que Date
, Calendar
, SimpleDateFormat
.
Convertissez votre Java.util.Date
(un moment en UTC) en un Instant
. Utilisez les nouvelles méthodes de conversion ajoutées aux anciennes classes.
Instant instant = myJavaUtilDate.toInstant() ;
Cela représente un moment en UTC. La détermination d'une date et d'une heure nécessite un fuseau horaire . A tout moment, la date et l'heure varient d'une zone à l'autre du globe. Par exemple, quelques minutes après minuit dans Paris France est un nouveau jour alors qu’il est encore «hier» dans Montréal Québec .
Si aucun fuseau horaire n'est spécifié, la machine virtuelle Java applique implicitement son fuseau horaire par défaut actuel. Cette valeur par défaut peut changer à tout moment pendant l'exécution (!), Ainsi vos résultats peuvent varier. Mieux vaut spécifier explicitement votre [fuseau horaire souhaité/attendu] [2] comme argument.
Spécifiez un nom du fuseau horaire } au format continent/region
, tel que America/Montreal
, Africa/Casablanca
ou Pacific/Auckland
. N'utilisez jamais les abréviations de 2 à 4 lettres telles que EST
ou IST
car elles sont pas de vrais fuseaux horaires, ni normalisés, ni même uniques (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Si vous souhaitez utiliser le fuseau horaire actuel par défaut de la JVM, demandez-le et transmettez-le en tant qu’argument. Si elle est omise, la valeur par défaut actuelle de la machine virtuelle Java est appliquée implicitement Mieux vaut être explicite, car la valeur par défaut peut être changée à tout moment pendant l'exécution par n'importe quel code de n'importe quel fil de n'importe quelle application de la JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Assignez la ZoneId
à la Instant
pour produire un objet ZonedDateTime
.
ZonedDateTime zdt = instant.atZone( z ) ;
Extrayez la partie heure du jour, sans la date ni le fuseau horaire.
LocalTime lt = zdt.toLocalTime() ;
Comparer. Calculer le temps écoulé avec un Duration
.
Duration d = Duration.between( ltStart , ltStop ) ;
Sachez que ceci n’est pas une comparaison juste. Les jours ne durent pas toujours 24 heures et toutes les valeurs horaires ne sont pas valables tous les jours dans toutes les zones. Par exemple, aux États-Unis, lors d’une commutation de l’heure d’été, il se peut qu’il n’y ait aucune heure. Ainsi, 1 heure du matin à 4 heures du matin peut durer 3 heures à une date, mais seulement 2 heures à une autre date.
Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes problématiques héritées _ date-heure telles que Java.util.Date
, Calendar
_, & SimpleDateFormat
.
Le projet Joda-Time , désormais en mode { mode maintenance }, conseille la migration vers les classes Java.time .
Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .
Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou une version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.*
classes.
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 _.
Si vous souhaitez comparer les valeurs binaires sous-jacentes (int long) des dates, vous pouvez procéder comme suit:
public int compareTimes(Date d1, Date d2)
{
int t1;
int t2;
t1 = (int) (d1.getTime() % (24*60*60*1000L));
t2 = (int) (d2.getTime() % (24*60*60*1000L));
return (t1 - t2);
}
Addendum 1
Cette technique présente l'avantage de la rapidité, car elle utilise directement la valeur long
sous-jacente des objets Date
, au lieu de la conversion entre les graduations et les composants du calendrier (ce qui est plutôt coûteux et lent). C'est aussi beaucoup plus simple que de jouer avec les objets Calendar
.
Addendum 2
Le code ci-dessus renvoie la différence de temps sous la forme d'une int
, qui sera correcte pour toutes les paires de temps, car il ignore entièrement les portions année/mois/jour des dates, et la différence entre deux fois est de 86 400 000 ms maximum = 1000 ms/sec × 60 sec/min × 60 min/h × 24 h/jour).
Vous pouvez envisager d'utiliser la fonction DateTimeComparator.getTimeOnlyInstance()
de l'heure Joda pour un comparateur comparant deux dates Joda uniquement en fonction de l'heure.
Par exemple:
DateTimeComparator comparator = DateTimeComparator.getTimeOnlyInstance();
comparator.compare(date1, date2);
Jetez un coup d’œil à la classe Calendar
. Il prend en charge l'extraction des heures, minutes et secondes de Date
donné.
Calendar calendar = Calendar.getInstance();
calendar.setTime(yourDateObject);
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
Si vous ne pouvez pas utiliser JODA,
créez 2 objets de calendrier, définissez l'année, le mois et le jour sur 0.
Comparez-les....
Si JODA n'est pas une option, l'une des approches les plus courtes consiste probablement à convertir le temps en chaînes, puis à les comparer.
DateFormat df = new SimpleDateFormat("HHmmssSZ");
df.format(date1).equals(df.format(date2));
si vous voulez simplement comparer la partie heure des dates, cela vous donnera le bon résultat -
public long compareTimes(Date d1, Date d2)
{
long t1;
long t2;
t1 = d1.getHours()*60*60+d1.getMinutes()*60+d1.getSeconds();
t2 = d2.getHours()*60*60+d2.getMinutes()*60+d2.getSeconds();
long diff = t1-t2;
System.out.println("t1 - "+t1+", t2 - "+t2+", diff - "+diff);
return diff;
}
Je ne sais pas à quel point elle est bien pratiquée ou efficace, mais j’ai écrit une fonction simple en utilisant l’objet Date qui sert à mes fins. Il retourne que true ou false est la première valeur de date supérieure à la seconde. Les entrées d1 && d2 sont des objets Date.
function CompareTimes(d1, d2) {
if (d1.getHours() < d2.getHours()) {
return false;
}
if (d1.getHours() > d2.getHours()) {
return true;
} else {
return (d1.getMinutes() > d2.getMinutes());
}
};