J'utilise la classe Java.util.Date
de Java dans Scala et je souhaite comparer un objet Date
à l'heure actuelle. Je sais que je peux calculer le delta en utilisant getTime ():
(new Java.util.Date()).getTime() - oldDate.getTime()
Cependant, cela me laisse juste avec une variable long
représentant millisecondes. Existe-t-il un moyen plus simple et plus agréable d’obtenir un delta temporel?
L'API JDK Date
est malheureusement horriblement endommagé. Je recommande d'utiliser Joda Time library .
Joda Time a une notion de temps Interval :
Interval interval = new Interval(oldTime, new Instant());
EDIT: En passant, Joda a deux concepts: Interval
pour représenter un intervalle de temps entre deux instants de temps (représente le temps entre 8h et 10h), et un Duration
qui représente une durée sans les limites de temps réelles !)
Si vous ne vous souciez que des comparaisons de temps, la plupart des implémentations Date
(y compris celle du JDK) implémentent l’interface Comparable
qui vous permet d’utiliser la fonction Comparable.compareTo()
/**
* Get a diff between two dates
* @param date1 the oldest date
* @param date2 the newest date
* @param timeUnit the unit in which you want the diff
* @return the diff value, in the provided unit
*/
public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {
long diffInMillies = date2.getTime() - date1.getTime();
return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
}
Et puis pouvez-vous appeler:
getDateDiff(date1,date2,TimeUnit.MINUTES);
pour obtenir le diff des 2 dates en unité minutes.
TimeUnit
est Java.util.concurrent.TimeUnit
, une énumération Java standard allant de quelques nanos à plusieurs jours.
public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {
long diffInMillies = date2.getTime() - date1.getTime();
//create the list
List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
Collections.reverse(units);
//create the result map of TimeUnit and difference
Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
long milliesRest = diffInMillies;
for ( TimeUnit unit : units ) {
//calculate difference in millisecond
long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
long diffInMilliesForUnit = unit.toMillis(diff);
milliesRest = milliesRest - diffInMilliesForUnit;
//put the result in the map
result.put(unit,diff);
}
return result;
}
La sortie est quelque chose comme Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
, avec les unités commandées.
Il vous suffit de convertir cette carte en une chaîne conviviale.
Les extraits de code ci-dessus calculent un diff simple entre 2 instants. Cela peut causer des problèmes lors d’un passage à l’heure avancée, comme expliqué dans cet article . Cela signifie que si vous calculez la différence entre les dates sans heure, il se peut qu’un jour/heure soit manquant.
À mon avis, le diff de date est un peu subjectif, surtout les jours. Tu peux:
compter le nombre d'heures écoulées: jour + 1 - jour = 1 jour = 24h
compter le nombre de temps écoulé en tenant compte de l'heure d'été: jour + 1 - jour = 1 = 24h (mais si vous utilisiez l'heure de minuit et l'heure avancée, cela pourrait être 0 jour et 23h)
compter le nombre de day switches
, ce qui signifie jour + 1 13h - jour 11h = 1 jour, même si le temps écoulé n'est que de 2h (ou 1h s'il y a une heure d'été: p)
Ma réponse est valide si votre définition de diff de jour correspond au 1er cas.
Si vous utilisez JodaTime, vous pouvez obtenir le diff pour deux dates (sauvegardées par millies, ReadableInstant) avec:
Interval interval = new Interval(oldInstant, new Instant());
Mais vous pouvez également obtenir le diff pour les dates/heures locales:
// returns 4 because of the leap year of 366 days
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5), PeriodType.years()).getYears()
// this time it returns 5
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5+1), PeriodType.years()).getYears()
// And you can also use these static methods
Years.yearsBetween(LocalDate.now(), LocalDate.now().plusDays(365*5)).getYears()
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime())
/ (1000 * 60 * 60 * 24) )
Notez que cela fonctionne avec les dates UTC. La différence peut donc être un jour de congé si vous regardez les dates locales. Et le faire fonctionner correctement avec les dates locales nécessite une approche complètement différente en raison de l'heure avancée.
Vous devez définir votre problème plus clairement. Vous pouvez prenez simplement le nombre de millisecondes entre les deux objets Date
et divisez-le par le nombre de millisecondes dans 24 heures, par exemple ... mais:
Date
est toujours en UTCUtilisation du framework Java.time intégré à Java 8+:
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println("ISO-8601: " + duration);
System.out.println("Minutes: " + duration.toMinutes());
Sortie:
ISO-8601: PT24H10M
Minutes: 1450
Pour plus d'informations, consultez les instructions Oracle Tutorial et ISO 8601 .
Convertissez vos objets Java.util.Date
obsolètes en leurs objets de remplacement, Java.time.Instant
. Calculez ensuite le temps écoulé sous la forme d'une Duration
.
Duration d =
Duration.between( // Calculate the span of time between two moments as a number of hours, minutes, and seconds.
myJavaUtilDate.toInstant() , // Convert legacy class to modern class by calling new method added to the old class.
Instant.now() // Capture the current moment in UTC. About two and a half hours later in this example.
)
;
d.toString (): PT2H34M56S
d.toMinutes (): 154
d.toMinutesPart (): 34
PnYnMnDTnHnMnS
La norme sensible ISO 8601 définit une représentation textuelle concise d'un intervalle de temps sous forme d'années, de mois, de jours, d'heures, etc. La norme appelle un tel intervalle un durée . Le format est PnYnMnDTnHnMnS
où P
signifie «période», T
sépare la partie date du moment et une valeur intermédiaire sépare les chiffres suivis d’une lettre.
Exemples:
P3Y6M4DT12H30M5S
PT4H30M
Le framework Java.time intégré à Java 8 et versions ultérieures supplante les anciennes classes fastidieuses Java.util.Date
Java.util.Calendar
. Les nouvelles classes s’inspirent du très réussi Joda-Time Framework, destiné à lui succéder, de concept similaire mais de nouvelle architecture. Défini par JSR 310 . Etendu par le projet ThreeTen-Extra . Voir le Tutorial .
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 instant = Instant.now() ; // Capture current moment in UTC.
Il est préférable d'éviter les classes héritées telles que Date
/Calendar
. Mais si vous devez interagir avec l'ancien code non encore mis à jour pour Java.time, effectuez la conversion. Appeler de nouvelles méthodes de conversion ajoutées aux anciennes classes. Pour passer d'un Java.util.Date
à un Instant
, appelez Date::toInstant
.
Instant instant = myJavaUtilDate.toInstant() ; // Convert from legacy `Java.util.Date` class to modern `Java.time.Instant` class.
Les classes Java.time ont divisé cette idée de représenter une période en plusieurs années, mois, jours, heures, minutes, secondes en deux parties:
Period
pendant des années, des mois, des joursDuration
pour les jours, heures, minutes, secondesVoici un exemple.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );
Dump à la console.
Period
et Duration
utilisent tous deux la norme ISO 8601 pour générer une représentation sous forme de chaîne de leur valeur.
System.out.println ( "now: " + now + " to future: " + now + " = " + duration );
maintenant: 2015-11-26T00: 46: 48.016-05: 00 [Amérique/Montréal] vers l'avenir: 2015-11-26T00: 46: 48.016-05: 00 [Amérique/Montréal] = PT1H3M
Java 9 ajoute des méthodes à Duration
pour obtenir la partie jours, la partie heures, la partie minutes et la partie secondes.
Vous pouvez obtenir le nombre total de jours, heures, minutes, secondes, millisecondes ou nanosecondes de la durée totale.
long totalHours = duration.toHours();
En Java 9, la classe Duration
obtient de nouvelles méthodes pour renvoyer les différentes parties de jours, heures, minutes, secondes, millisecondes/nanosecondes. Appelez les méthodes to…Part
: toDaysPart()
, toHoursPart()
et ainsi de suite.
ChronoUnit
Si vous ne vous souciez que d'une granularité de temps plus longue et simple, telle que «nombre de jours écoulés», utilisez l'énumération ChronoUnit
.
long daysElapsed = ChronoUnit.DAYS.between( earlier , later );
Un autre exemple.
Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );
…
long minutesElapsed = ChronoUnit.MINUTES.between( now , later );
120
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 la migration vers 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 _.
UPDATE: le projet Joda-Time est maintenant en mode maintenance , avec l'équipe conseillant la migration vers les classes Java.time . Je laisse cette section intacte pour l'histoire.
La bibliothèque Joda-Time utilise ISO 8601 pour ses valeurs par défaut. Sa classe Period
analyse et génère ces chaînes PnYnMnDTnHnMnS.
DateTime now = DateTime.now(); // Caveat: Ignoring the important issue of time zones.
Period period = new Period( now, now.plusHours( 4 ).plusMinutes( 30));
System.out.println( "period: " + period );
Renders:
period: PT4H30M
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();
Une alternative un peu plus simple:
System.currentTimeMillis() - oldDate.getTime()
Quant à "plus gentil": eh bien, de quoi avez-vous besoin exactement? Le problème avec la représentation des durées sous forme de nombre d’heures et de jours, etc., c’est qu’il peut en résulter des inexactitudes et des attentes erronées en raison de la complexité des dates (par exemple, les journées peuvent durer 23 ou 25 heures en raison de l’heure avancée).
L'utilisation de l'approche milliseconde peut poser des problèmes dans certains environnements locaux.
Prenons, par exemple, la différence entre les deux dates du 24/03/2007 et du 25/03/2007 devrait être de 1 jour;
Cependant, en utilisant la route en millisecondes, vous aurez 0 jour, si vous utilisez ceci au Royaume-Uni!
/** Manual Method - YIELDS INCORRECT RESULTS - DO NOT USE**/
/* This method is used to find the no of days between the given dates */
public long calculateDays(Date dateEarly, Date dateLater) {
return (dateLater.getTime() - dateEarly.getTime()) / (24 * 60 * 60 * 1000);
}
Une meilleure façon de le faire est d’utiliser Java.util.Calendar
/** Using Calendar - THE CORRECT WAY**/
public static long daysBetween(Calendar startDate, Calendar endDate) {
Calendar date = (Calendar) startDate.clone();
long daysBetween = 0;
while (date.before(endDate)) {
date.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
return daysBetween;
}
Il y a plusieurs façons de trouver la différence entre les dates et les heures. Une des manières les plus simples que je connaisse serait:
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.set(2012, 04, 02);
calendar2.set(2012, 04, 04);
long milsecs1= calendar1.getTimeInMillis();
long milsecs2 = calendar2.getTimeInMillis();
long diff = milsecs2 - milsecs1;
long dsecs = diff / 1000;
long dminutes = diff / (60 * 1000);
long dhours = diff / (60 * 60 * 1000);
long ddays = diff / (24 * 60 * 60 * 1000);
System.out.println("Your Day Difference="+ddays);
La déclaration d'impression n'est qu'un exemple - vous pouvez la formater comme bon vous semble.
Toutes les réponses étant correctes, mais utilisant des bibliothèques Java ou tierces tierces telles que joda ou similaire, je vais simplement laisser tomber une autre méthode en utilisant les nouvelles classes Java.time dans Java 8 et versions ultérieures. Voir Tutoriel Oracle .
Utilisez LocalDate
et ChronoUnit
:
LocalDate d1 = LocalDate.of(2017, 5, 1);
LocalDate d2 = LocalDate.of(2017, 5, 18);
long days = ChronoUnit.DAYS.between(d1, d2);
System.out.println( days );
Soustraire les dates en millisecondes fonctionne (comme décrit dans un autre article), mais vous devez pour utiliser HOUR_OF_DAY et non HOUR lorsque vous effacez les plages horaires de vos dates:
public static final long MSPERDAY = 60 * 60 * 24 * 1000;
...
final Calendar dateStartCal = Calendar.getInstance();
dateStartCal.setTime(dateStart);
dateStartCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateStartCal.set(Calendar.MINUTE, 0);
dateStartCal.set(Calendar.SECOND, 0);
dateStartCal.set(Calendar.MILLISECOND, 0);
final Calendar dateEndCal = Calendar.getInstance();
dateEndCal.setTime(dateEnd);
dateEndCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateEndCal.set(Calendar.MINUTE, 0);
dateEndCal.set(Calendar.SECOND, 0);
dateEndCal.set(Calendar.MILLISECOND, 0);
final long dateDifferenceInDays = ( dateStartCal.getTimeInMillis()
- dateEndCal.getTimeInMillis()
) / MSPERDAY;
if (dateDifferenceInDays > 15) {
// Do something if difference > 15 days
}
Jetez un coup d'œil à Joda Time , qui est une API Date/Time améliorée pour Java et qui devrait bien fonctionner avec Scala.
Si vous ne souhaitez pas utiliser JodaTime ou similaire, la meilleure solution est probablement la suivante:
final static long MILLIS_PER_DAY = 24 * 3600 * 1000;
long msDiff= date1.getTime() - date2.getTime();
long daysDiff = Math.round(msDiff / ((double)MILLIS_PER_DAY));
Le nombre de ms par jour n'est pas toujours le même (en raison de l'heure d'été et des secondes intercalaires), mais il est très proche et au moins les écarts dus à l'heure d'été s'annulent sur des périodes plus longues. Par conséquent, diviser et arrondir donnera un résultat correct (au moins tant que le calendrier local utilisé ne contient pas de sauts temporels étranges autres que l'heure d'été et les secondes intercalaires).
Notez que cela suppose toujours que date1
et date2
sont définis à la même heure de la journée. Pour différents moments de la journée, vous devez d’abord définir ce que «différence de date» signifie, comme l’a souligné Jon Skeet.
Laissez-moi montrer la différence entre Joda Interval et Days:
DateTime start = new DateTime(2012, 2, 6, 10, 44, 51, 0);
DateTime end = new DateTime(2012, 2, 6, 11, 39, 47, 1);
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
System.out.println(period.getYears() + " years, " + period.getMonths() + " months, " + period.getWeeks() + " weeks, " + period.getDays() + " days");
System.out.println(period.getHours() + " hours, " + period.getMinutes() + " minutes, " + period.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *1 weeks, 1 days*
//0 hours, 54 minutes, 56 seconds
//Period can set PeriodType,such as PeriodType.yearMonthDay(),PeriodType.yearDayTime()...
Period p = new Period(start, end, PeriodType.yearMonthDayTime());
System.out.println(p.getYears() + " years, " + p.getMonths() + " months, " + p.getWeeks() + " weeks, " + p.getDays() + "days");
System.out.println(p.getHours() + " hours, " + p.getMinutes() + " minutes, " + p.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *0 weeks, 8 days*
//0 hours, 54 minutes, 56 seconds
Si vous avez besoin d’une chaîne de retour formatée telle que , "2 jours 03h 42m 07s", essayez ceci:
public String fill2(int value)
{
String ret = String.valueOf(value);
if (ret.length() < 2)
ret = "0" + ret;
return ret;
}
public String get_duration(Date date1, Date date2)
{
TimeUnit timeUnit = TimeUnit.SECONDS;
long diffInMilli = date2.getTime() - date1.getTime();
long s = timeUnit.convert(diffInMilli, TimeUnit.MILLISECONDS);
long days = s / (24 * 60 * 60);
long rest = s - (days * 24 * 60 * 60);
long hrs = rest / (60 * 60);
long rest1 = rest - (hrs * 60 * 60);
long min = rest1 / 60;
long sec = s % 60;
String dates = "";
if (days > 0) dates = days + " Days ";
dates += fill2((int) hrs) + "h ";
dates += fill2((int) min) + "m ";
dates += fill2((int) sec) + "s ";
return dates;
}
public static String getDifferenceBtwTime(Date dateTime) {
long timeDifferenceMilliseconds = new Date().getTime() - dateTime.getTime();
long diffSeconds = timeDifferenceMilliseconds / 1000;
long diffMinutes = timeDifferenceMilliseconds / (60 * 1000);
long diffHours = timeDifferenceMilliseconds / (60 * 60 * 1000);
long diffDays = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24);
long diffWeeks = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 7);
long diffMonths = (long) (timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 30.41666666));
long diffYears = (long)(timeDifferenceMilliseconds / (1000 * 60 * 60 * 24 * 365));
if (diffSeconds < 1) {
return "one sec ago";
} else if (diffMinutes < 1) {
return diffSeconds + " seconds ago";
} else if (diffHours < 1) {
return diffMinutes + " minutes ago";
} else if (diffDays < 1) {
return diffHours + " hours ago";
} else if (diffWeeks < 1) {
return diffDays + " days ago";
} else if (diffMonths < 1) {
return diffWeeks + " weeks ago";
} else if (diffYears < 12) {
return diffMonths + " months ago";
} else {
return diffYears + " years ago";
}
}
Voir l'exemple ici http://www.roseindia.net/Java/beginners/DateDifferent.shtml Cet exemple vous donne la différence en jours, heures, minutes, secondes et millisecondes :).
import Java.util.Calendar;
import Java.util.Date;
public class DateDifferent {
public static void main(String[] args) {
Date date1 = new Date(2009, 01, 10);
Date date2 = new Date(2009, 07, 01);
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.setTime(date1);
calendar2.setTime(date2);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
long diffSeconds = diff / 1000;
long diffMinutes = diff / (60 * 1000);
long diffHours = diff / (60 * 60 * 1000);
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.println("\nThe Date Different Example");
System.out.println("Time in milliseconds: " + diff + " milliseconds.");
System.out.println("Time in seconds: " + diffSeconds + " seconds.");
System.out.println("Time in minutes: " + diffMinutes + " minutes.");
System.out.println("Time in hours: " + diffHours + " hours.");
System.out.println("Time in days: " + diffDays + " days.");
}
}
Le code suivant peut vous donner le résultat souhaité:
String startDate = "Jan 01 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
LocalDate date = LocalDate.parse(startDate, formatter);
String currentDate = "Feb 11 2015";
LocalDate date1 = LocalDate.parse(currentDate, formatter);
System.out.println(date1.toEpochDay() - date.toEpochDay());
Utilisez le fuseau horaire GMT pour obtenir une instance du calendrier, définissez l'heure à l'aide de la méthode set de la classe Calendar. Le fuseau horaire GMT a un décalage 0 (pas vraiment important) et l'indicateur d'heure d'été défini sur false.
final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.set(Calendar.YEAR, 2011);
cal.set(Calendar.MONTH, 9);
cal.set(Calendar.DAY_OF_MONTH, 29);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
final Date startDate = cal.getTime();
cal.set(Calendar.YEAR, 2011);
cal.set(Calendar.MONTH, 12);
cal.set(Calendar.DAY_OF_MONTH, 21);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
final Date endDate = cal.getTime();
System.out.println((endDate.getTime() - startDate.getTime()) % (1000l * 60l * 60l * 24l));
int daysDiff = (date1.getTime() - date2.getTime()) / MILLIS_PER_DAY;
La meilleure chose à faire est
(Date1-Date2)/86 400 000
Ce nombre est le nombre de millisecondes par jour.
Une date-autre date vous donne la différence en millisecondes.
Recueillir la réponse dans un double variable.
Juste pour répondre à la question initiale:
Placez le code suivant dans une fonction telle que Long getAge () {}
Date dahora = new Date();
long MillisToYearsByDiv = 1000l *60l * 60l * 24l * 365l;
long javaOffsetInMillis = 1990l * MillisToYearsByDiv;
long realNowInMillis = dahora.getTime() + javaOffsetInMillis;
long realBirthDayInMillis = this.getFechaNac().getTime() + javaOffsetInMillis;
long ageInMillis = realNowInMillis - realBirthDayInMillis;
return ageInMillis / MillisToYearsByDiv;
Le plus important ici est de travailler avec des nombres longs pour la multiplication et la division. Et bien sûr, le décalage que Java applique dans son calcul de dates.
:)
Après avoir parcouru toutes les autres réponses, conserver le type de date Java 7 mais être plus précis/standard avec l’approche Java 8 diff,
public static long daysBetweenDates(Date d1, Date d2) {
Instant instant1 = d1.toInstant();
Instant instant2 = d2.toInstant();
long diff = ChronoUnit.DAYS.between(instant1, instant2);
return diff;
}
Depuis la question est tagué avec Scala,
import scala.concurrent.duration._
val diff = (System.currentTimeMillis() - oldDate.getTime).milliseconds
val diffSeconds = diff.toSeconds
val diffMinutes = diff.toMinutes
val diffHours = diff.toHours
val diffDays = diff.toDays
Ne pas utiliser l'API standard, non. Vous pouvez faire le vôtre en faisant quelque chose comme ça:
class Duration {
private final TimeUnit unit;
private final long length;
// ...
}
Ou vous pouvez utiliser Joda :
DateTime a = ..., b = ...;
Duration d = new Duration(a, b);
C’est probablement la façon la plus simple de le faire - c’est peut-être parce que je code depuis Java (avec ses bibliothèques de date et d’heure certes maladroites), mais ce code me semble «simple et agréable»!
Etes-vous satisfait du résultat renvoyé en millisecondes ou souhaitez-vous qu’une partie de votre question vous demande de le renvoyer sous un autre format?
Voici une solution Java 7 correcte dans O(1) sans aucune dépendance.
public static int countDaysBetween(Date date1, Date date2) {
Calendar c1 = removeTime(from(date1));
Calendar c2 = removeTime(from(date2));
if (c1.get(YEAR) == c2.get(YEAR)) {
return Math.abs(c1.get(DAY_OF_YEAR) - c2.get(DAY_OF_YEAR)) + 1;
}
// ensure c1 <= c2
if (c1.get(YEAR) > c2.get(YEAR)) {
Calendar c = c1;
c1 = c2;
c2 = c;
}
int y1 = c1.get(YEAR);
int y2 = c2.get(YEAR);
int d1 = c1.get(DAY_OF_YEAR);
int d2 = c2.get(DAY_OF_YEAR);
return d2 + ((y2 - y1) * 365) - d1 + countLeapYearsBetween(y1, y2) + 1;
}
private static int countLeapYearsBetween(int y1, int y2) {
if (y1 < 1 || y2 < 1) {
throw new IllegalArgumentException("Year must be > 0.");
}
// ensure y1 <= y2
if (y1 > y2) {
int i = y1;
y1 = y2;
y2 = i;
}
int diff = 0;
int firstDivisibleBy4 = y1;
if (firstDivisibleBy4 % 4 != 0) {
firstDivisibleBy4 += 4 - (y1 % 4);
}
diff = y2 - firstDivisibleBy4 - 1;
int divisibleBy4 = diff < 0 ? 0 : diff / 4 + 1;
int firstDivisibleBy100 = y1;
if (firstDivisibleBy100 % 100 != 0) {
firstDivisibleBy100 += 100 - (firstDivisibleBy100 % 100);
}
diff = y2 - firstDivisibleBy100 - 1;
int divisibleBy100 = diff < 0 ? 0 : diff / 100 + 1;
int firstDivisibleBy400 = y1;
if (firstDivisibleBy400 % 400 != 0) {
firstDivisibleBy400 += 400 - (y1 % 400);
}
diff = y2 - firstDivisibleBy400 - 1;
int divisibleBy400 = diff < 0 ? 0 : diff / 400 + 1;
return divisibleBy4 - divisibleBy100 + divisibleBy400;
}
public static Calendar from(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
return c;
}
public static Calendar removeTime(Calendar c) {
c.set(HOUR_OF_DAY, 0);
c.set(MINUTE, 0);
c.set(SECOND, 0);
c.set(MILLISECOND, 0);
return c;
}
Remarque: startDate et endDates sont -> Java.util.Date
import org.joda.time.Duration;
import org.joda.time.Interval;
Interval interval = new Interval(startDate.getTime(), endDate.getTime);
Duration period = interval.toDuration();
period.getStandardDays() //gives the number of days elapsed between start and end date
Semblable aux jours, vous pouvez également obtenir des heures, minutes et secondes
period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();
Après avoir lu de nombreuses réponses et commentaires à cette question, j'ai eu l'impression qu'il fallait soit utiliser l'heure Joda, soit tenir compte de certaines particularités de l'heure d'été, etc. Comme je ne voulais pas faire En fin de compte, j’ai écrit quelques lignes de code pour calculer la différence entre deux dates sans utiliser de classes Java liées à la date ou à l’heure.
Dans le code ci-dessous, les chiffres de l'année, du mois et du jour sont les mêmes que dans la vie réelle. Par exemple, le 24 décembre 2015, l'année = 2015, le mois = 12 et le jour = 24.
Je souhaite partager ce code au cas où quelqu'un d'autre voudrait l'utiliser. Il y a 3 méthodes: 1) Une méthode pour déterminer si une année donnée est une année bissextile 2) Une méthode pour calculer le nombre d'un jour donné par rapport au 1er janvier d'une année donnée 3) Une méthode pour calculer le nombre de jours entre deux dates quelconques selon la méthode 2 (numéro de la date de fin moins numéro de la date de début).
Voici les méthodes:
1)
public static boolean isLeapYear (int year) {
//Every 4. year is a leap year, except if the year is divisible by 100 and not by 400
//For example 1900 is not a leap year but 2000 is
boolean result = false;
if (year % 4 == 0) {
result = true;
}
if (year % 100 == 0) {
result = false;
}
if (year % 400 == 0) {
result = true;
}
return result;
}
2)
public static int daysGoneSince (int yearZero, int year, int month, int day) {
//Calculates the day number of the given date; day 1 = January 1st in the yearZero
//Validate the input
if (year < yearZero || month < 1 || month > 12 || day < 1 || day > 31) {
//Throw an exception
throw new IllegalArgumentException("Too many or too few days in month or months in year or the year is smaller than year zero");
}
else if (month == 4 || month == 6 || month == 9 || month == 11) {//Months with 30 days
if (day == 31) {
//Throw an exception
throw new IllegalArgumentException("Too many days in month");
}
}
else if (month == 2) {//February 28 or 29
if (isLeapYear(year)) {
if (day > 29) {
//Throw an exception
throw new IllegalArgumentException("Too many days in month");
}
}
else if (day > 28) {
//Throw an exception
throw new IllegalArgumentException("Too many days in month");
}
}
//Start counting days
int days = 0;
//Days in the target month until the target day
days = days + day;
//Days in the earlier months in the target year
for (int i = 1; i < month; i++) {
switch (i) {
case 1: case 3: case 5:
case 7: case 8: case 10:
case 12:
days = days + 31;
break;
case 2:
days = days + 28;
if (isLeapYear(year)) {
days = days + 1;
}
break;
case 4: case 6: case 9: case 11:
days = days + 30;
break;
}
}
//Days in the earlier years
for (int i = yearZero; i < year; i++) {
days = days + 365;
if (isLeapYear(i)) {
days = days + 1;
}
}
return days;
}
3)
public static int dateDiff (int startYear, int startMonth, int startDay, int endYear, int endMonth, int endDay) {
int yearZero;
//daysGoneSince presupposes that the first argument be smaller or equal to the second argument
if (10000 * startYear + 100 * startMonth + startDay > 10000 * endYear + 100 * endMonth + endDay) {//If the end date is earlier than the start date
yearZero = endYear;
}
else {
yearZero = startYear;
}
return daysGoneSince(yearZero, endYear, endMonth, endDay) - daysGoneSince(yearZero, startYear, startMonth, startDay);
}
Les versions antérieures de Java, vous pouvez essayer.
public static String daysBetween(Date createdDate, Date expiryDate) {
Calendar createdDateCal = Calendar.getInstance();
createdDateCal.clear();
createdDateCal.setTime(createdDate);
Calendar expiryDateCal = Calendar.getInstance();
expiryDateCal.clear();
expiryDateCal.setTime(expiryDate);
long daysBetween = 0;
while (createdDateCal.before(expiryDateCal)) {
createdDateCal.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
return daysBetween+"";
}
Puisque vous utilisez Scala, il existe une très bonne bibliothèque Scala Lamma . Avec Lamma, vous pouvez réduire la date directement avec l'opérateur -
scala> Date(2015, 5, 5) - 2 // minus days by int
res1: io.lamma.Date = Date(2015,5,3)
scala> Date(2015, 5, 15) - Date(2015, 5, 8) // minus two days => difference between two days
res2: Int = 7
essaye ça:
int Epoch = (int) (new Java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse("01/01/1970 00:00:00").getTime() / 1000);
vous pouvez éditer la chaîne dans le param de méthodes parse ().
Utilisez simplement la méthode ci-dessous avec deux objets Date
. Si vous voulez passer la date actuelle, il suffit de passer new Date()
en tant que deuxième paramètre car il est initialisé avec l'heure actuelle.
public String getDateDiffString(Date dateOne, Date dateTwo)
{
long timeOne = dateOne.getTime();
long timeTwo = dateTwo.getTime();
long oneDay = 1000 * 60 * 60 * 24;
long delta = (timeTwo - timeOne) / oneDay;
if (delta > 0) {
return "dateTwo is " + delta + " days after dateOne";
}
else {
delta *= -1;
return "dateTwo is " + delta + " days before dateOne";
}
}
En outre, mis à part le nombre de jours, si vous souhaitez utiliser une autre différence de paramètre, utilisez l’extrait ci-dessous,
int year = delta / 365;
int rest = delta % 365;
int month = rest / 30;
rest = rest % 30;
int weeks = rest / 7;
int days = rest % 7;
Le code P.S provient entièrement d'une réponse SO.
Il existe un moyen simple de le faire en Java.
// crée une méthode utilitaire
public long getDaysBetweenDates(Date d1, Date d2){
return TimeUnit.MILLISECONDS.toDays(d1.getTime() - d2.getTime());
}
Cette méthode renverra le nombre de jours entre les 2 dates. Soit vous pouvez utiliser le format de date Java par défaut, soit convertir tout format de date.
Voici une solution, car il existe de nombreuses façons d’y parvenir:
import Java.util.*;
int syear = 2000;
int eyear = 2000;
int smonth = 2;//Feb
int emonth = 3;//Mar
int sday = 27;
int eday = 1;
Date startDate = new Date(syear-1900,smonth-1,sday);
Date endDate = new Date(eyear-1900,emonth-1,eday);
int difInDays = (int) ((endDate.getTime() - startDate.getTime())/(1000*60*60*24));
Ceci est un autre échantillon. Ce qui fonctionne fondamentalement pour un motif défini par l'utilisateur.
public static LinkedHashMap<String, Object> checkDateDiff(DateTimeFormatter dtfObj, String startDate, String endDate)
{
Map<String, Object> dateDiffMap = new HashMap<String, Object>();
DateTime start = DateTime.parse(startDate,dtfObj);
DateTime end = DateTime.parse(endDate,dtfObj);
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
dateDiffMap.put("ISO-8601_PERIOD_FORMAT", period);
dateDiffMap.put("YEAR", period.getYears());
dateDiffMap.put("MONTH", period.getMonths());
dateDiffMap.put("WEEK", period.getWeeks());
dateDiffMap.put("DAY", period.getWeeks());
dateDiffMap.put("HOUR", period.getHours());
dateDiffMap.put("MINUTE", period.getMinutes());
dateDiffMap.put("SECOND", period.getSeconds());
return dateDiffMap;
}
J'ai apprécié l'approche basée sur TimeUnit jusqu'à ce que je découvre qu'elle ne couvre que les cas triviaux dans lesquels le nombre de combien d'unités d'un unité temporelle se trouvent dans l'unité supérieure est fixe. Cela se sépare lorsque vous voulez savoir combien de mois, d'année, etc.
il existe une méthode de comptage moins efficace que d’autres, mais elle semble fonctionner pour moi et prend également en compte l’heure d’été.
public static String getOffsetAsString( Calendar cNow, Calendar cThen) {
Calendar cBefore;
Calendar cAfter;
if ( cNow.getTimeInMillis() < cThen.getTimeInMillis()) {
cBefore = ( Calendar) cNow.clone();
cAfter = cThen;
} else {
cBefore = ( Calendar) cThen.clone();
cAfter = cNow;
}
// compute diff
Map<Integer, Long> diffMap = new HashMap<Integer, Long>();
int[] calFields = { Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND};
for ( int i = 0; i < calFields.length; i++) {
int field = calFields[ i];
long d = computeDist( cAfter, cBefore, field);
diffMap.put( field, d);
}
final String result = String.format( "%dY %02dM %dT %02d:%02d:%02d.%03d",
diffMap.get( Calendar.YEAR), diffMap.get( Calendar.MONTH), diffMap.get( Calendar.DAY_OF_MONTH), diffMap.get( Calendar.HOUR_OF_DAY), diffMap.get( Calendar.MINUTE), diffMap.get( Calendar.SECOND), diffMap.get( Calendar.MILLISECOND));
return result;
}
private static int computeDist( Calendar cAfter, Calendar cBefore, int field) {
cBefore.setLenient( true);
System.out.print( "D " + new Date( cBefore.getTimeInMillis()) + " --- " + new Date( cAfter.getTimeInMillis()) + ": ");
int count = 0;
if ( cAfter.getTimeInMillis() > cBefore.getTimeInMillis()) {
int fVal = cBefore.get( field);
while ( cAfter.getTimeInMillis() >= cBefore.getTimeInMillis()) {
count++;
fVal = cBefore.get( field);
cBefore.set( field, fVal + 1);
System.out.print( count + "/" + ( fVal + 1) + ": " + new Date( cBefore.getTimeInMillis()) + " ] ");
}
int result = count - 1;
cBefore.set( field, fVal);
System.out.println( "" + result + " at: " + field + " cb = " + new Date( cBefore.getTimeInMillis()));
return result;
}
return 0;
}
Si vous voulez résoudre le problème des plages de dates qui franchissent la limite de l'heure d'été (par exemple, une date en été et l'autre en hiver), vous pouvez l'utiliser pour obtenir la différence en jours:
public static long calculateDifferenceInDays(Date start, Date end, Locale locale) {
Calendar cal = Calendar.getInstance(locale);
cal.setTime(start);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long startTime = cal.getTimeInMillis();
cal.setTime(end);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long endTime = cal.getTimeInMillis();
// calculate the offset if one of the dates is in summer time and the other one in winter time
TimeZone timezone = cal.getTimeZone();
int offsetStart = timezone.getOffset(startTime);
int offsetEnd = timezone.getOffset(endTime);
int offset = offsetEnd - offsetStart;
return TimeUnit.MILLISECONDS.toDays(endTime - startTime + offset);
}
public static void main(String[] args) {
String dateStart = "01/14/2012 09:29:58";
String dateStop = "01/14/2012 10:31:48";
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
DateTime date11 = new DateTime(d1);
DateTime date22 = new DateTime(d2);
int days = Days.daysBetween(date11.withTimeAtStartOfDay(), date22.withTimeAtStartOfDay()).getDays();
int hours = Hours.hoursBetween(date11, date22).getHours() % 24;
int minutes = Minutes.minutesBetween(date11, date22).getMinutes() % 60;
int seconds = Seconds.secondsBetween(date11, date22).getSeconds() % 60;
if (hours > 0 || minutes > 0 || seconds > 0) {
days = days + 1;
}
System.out.println(days);
} catch (Exception e) {
e.printStackTrace();
}
}
Cela donnera date diff pour le même jour aussi
Une autre variante Java pure:
public boolean isWithin30Days(Calendar queryCalendar) {
// 1. Take the date you are checking, and roll it back N days
Calendar queryCalMinus30Days = Calendar.getInstance();
queryCalMinus30Days.setTime(queryCalendar.getTime());
queryCalMinus30Days.add(Calendar.DATE, -30); // subtract 30 days from the calendar
// 2. Get respective milliseconds for the two Calendars: now & queryCal minus N days
long nowL = Calendar.getInstance().getTimeInMillis();
long queryCalMinus30DaysL = queryCalMinus30Days.getTimeInMillis();
// 3. if nowL is still less than the queryCalMinus30DaysL, it means queryCalendar is more than 30 days into future
boolean isWithin30Days = nowL >= queryCalMinus30DaysL;
return isWithin30Days;
}
merci au code de démarrage ici: https://stackoverflow.com/a/30207726/2162226
La réponse de @Michael Borgwardt ne fonctionne pas correctement sous Android. Les erreurs d'arrondis existent. Exemple 19 au 21 mai dit 1 jour car il lance 1,99 à 1. Utilisez round avant de lancer int.
Réparer
int diffInDays = (int)Math.round(( (newerDate.getTime() - olderDate.getTime())
/ (1000 * 60 * 60 * 24) ))
Notez que cela fonctionne avec les dates UTC. La différence peut donc être un jour de congé si vous regardez les dates locales. Et le faire fonctionner correctement avec les dates locales nécessite une approche complètement différente en raison de l'heure avancée.