how to calculate the difference between 2 dates in java? [duplicate] - java

I'm using Java's java.util.Date class in Scala and want to compare a Date object and the current time. I know I can calculate the delta by using getTime():
(new java.util.Date()).getTime() - oldDate.getTime()
However, this just leaves me with a long representing milliseconds. Is there any simpler, nicer way to get a time delta?

Simple diff (without lib)
/**
* 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);
}
And then can you call:
getDateDiff(date1,date2,TimeUnit.MINUTES);
to get the diff of the 2 dates in minutes unit.
TimeUnit is java.util.concurrent.TimeUnit, a standard Java enum going from nanos to days.
Human readable diff (without lib)
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;
}
http://ideone.com/5dXeu6
The output is something like Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}, with the units ordered.
You just have to convert that map to a user-friendly string.
Warning
The above code snippets compute a simple diff between 2 instants. It can cause problems during a daylight saving switch, like explained in this post. This means if you compute the diff between dates with no time you may have a missing day/hour.
In my opinion the date diff is kind of subjective, especially on days. You may:
count the number of 24h elapsed time: day+1 - day = 1 day = 24h
count the number of elapsed time, taking care of daylight savings: day+1 - day = 1 = 24h (but using midnight time and daylight savings it could be 0 day and 23h)
count the number of day switches, which means day+1 1pm - day 11am = 1 day, even if the elapsed time is just 2h (or 1h if there is a daylight saving :p)
My answer is valid if your definition of date diff on days match the 1st case
With JodaTime
If you are using JodaTime you can get the diff for 2 instants (millies backed ReadableInstant) dates with:
Interval interval = new Interval(oldInstant, new Instant());
But you can also get the diff for Local dates/times:
// 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()

The JDK Date API is horribly broken unfortunately. I recommend using Joda Time library.
Joda Time has a concept of time Interval:
Interval interval = new Interval(oldTime, new Instant());
EDIT: By the way, Joda has two concepts: Interval for representing an interval of time between two time instants (represent time between 8am and 10am), and a Duration that represents a length of time without the actual time boundaries (e.g. represent two hours!)
If you only care about time comparisions, most Date implementations (including the JDK one) implements Comparable interface which allows you to use the Comparable.compareTo()

int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime())
/ (1000 * 60 * 60 * 24) )
Note that this works with UTC dates, so the difference may be a day off if you look at local dates. And getting it to work correctly with local dates requires a completely different approach due to daylight savings time.

Using the java.time framework built into 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());
Output:
ISO-8601: PT24H10M
Minutes: 1450
For more info, see the Oracle Tutorial and the ISO 8601 standard.

tl;dr
Convert your obsolete java.util.Date objects to their replacement, java.time.Instant. Then calculate the elapsed time as a 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
ISO 8601 Format: PnYnMnDTnHnMnS
The sensible standard ISO 8601 defines a concise textual representation of a span of time as a number of years, months, days, hours, etc. The standard calls such such a span a duration. The format is PnYnMnDTnHnMnS where the P means "Period", the T separates the date portion from the time portion, and in between are numbers followed by a letter.
Examples:
P3Y6M4DT12H30M5Sthree years, six months, four days, twelve hours, thirty minutes, and five seconds
PT4H30MFour and a half hours
java.time
The java.time framework built into Java 8 and later supplants the troublesome old java.util.Date/java.util.Calendar classes. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
Moment
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now() ; // Capture current moment in UTC.
Best to avoid the legacy classes such as Date/Calendar. But if you must inter-operate with old code not yet updated to java.time, convert back and forth. Call new conversion methods added to the old classes. For moving from a java.util.Date to an Instant, call Date::toInstant.
Instant instant = myJavaUtilDate.toInstant() ; // Convert from legacy `java.util.Date` class to modern `java.time.Instant` class.
Span of time
The java.time classes have split this idea of representing a span of time as a number of years, months, days, hours, minutes, seconds into two halves:
Period for years, months, days
Duration for days, hours, minutes, seconds
Here is an example.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );
Dump to console.
Both Period and Duration use the ISO 8601 standard for generating a String representation of their value.
System.out.println ( "now: " + now + " to future: " + now + " = " + duration );
now: 2015-11-26T00:46:48.016-05:00[America/Montreal] to future: 2015-11-26T00:46:48.016-05:00[America/Montreal] = PT1H3M
Java 9 adds methods to Duration to get the days part, hours part, minutes part, and seconds part.
You can get the total number of days or hours or minutes or seconds or milliseconds or nanoseconds in the entire Duration.
long totalHours = duration.toHours();
In Java 9 the Duration class gets new methods for returning the various parts of days, hours, minutes, seconds, milliseconds/nanoseconds. Call the to…Part methods: toDaysPart(), toHoursPart(), and so on.
ChronoUnit
If you only care about a simpler larger granularity of time, such as “number of days elapsed”, use the ChronoUnit enum.
long daysElapsed = ChronoUnit.DAYS.between( earlier , later );
Another example.
Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );
…
long minutesElapsed = ChronoUnit.MINUTES.between( now , later );
120
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Joda-Time
UPDATE: The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. I leave this section intact for history.
The Joda-Time library uses ISO 8601 for its defaults. Its Period class parses and generates these PnYnMnDTnHnMnS strings.
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

You need to define your problem more clearly. You could just take the number of milliseconds between the two Date objects and divide by the number of milliseconds in 24 hours, for example... but:
This won't take time zones into consideration - Date is always in UTC
This won't take daylight saving time into consideration (where there can be days which are only 23 hours long, for example)
Even within UTC, how many days are there in August 16th 11pm to August 18th 2am? It's only 27 hours, so does that mean one day? Or should it be three days because it covers three dates?

Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();
https://www.joda.org/joda-time/faq.html#datediff

A slightly simpler alternative:
System.currentTimeMillis() - oldDate.getTime()
As for "nicer": well, what exactly do you need? The problem with representing time durations as a number of hours and days etc. is that it may lead to inaccuracies and wrong expectations due to the complexity of dates (e.g. days can have 23 or 25 hours due to daylight savings time).

Using millisecond approach can cause problems in some locales.
Lets take, for example, the difference between the two dates 03/24/2007 and 03/25/2007 should be 1 day;
However, using the millisecond route, you'll get 0 days, if you run this in the UK!
/** 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);
}
Better way to implement this is to use 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;
}

Since all the answers here are correct but use legacy java or 3rd party libs like joda or similar, I will just drop another way using new java.time classes in Java 8 and later. See Oracle Tutorial.
Use LocalDate and 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 );

There are many ways you can find the difference between dates & times. One of the simplest ways that I know of would be:
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);
The print statement is just an example - you can format it, the way you like.

If you don't want to use JodaTime or similar, the best solution is probably this:
final static long MILLIS_PER_DAY = 24 * 3600 * 1000;
long msDiff= date1.getTime() - date2.getTime();
long daysDiff = Math.round(msDiff / ((double)MILLIS_PER_DAY));
The number of ms per day is not always the same (because of daylight saving time and leap seconds), but it's very close, and at least deviations due to daylight saving time cancel out over longer periods. Therefore dividing and then rounding will give a correct result (at least as long as the local calendar used does not contain weird time jumps other than DST and leap seconds).
Note that this still assumes that date1 and date2 are set to the same time of day. For different times of day, you'd first have to define what "date difference" means, as pointed out by Jon Skeet.

Subtracting the dates in milliseconds works (as described in another post), but you have to use HOUR_OF_DAY and not HOUR when clearing the time parts of your 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
}

Take a look at Joda Time, which is an improved Date/Time API for Java and should work fine with Scala.

int daysDiff = (date1.getTime() - date2.getTime()) / MILLIS_PER_DAY;

Let me show difference between Joda Interval and 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

If you need a formatted return String like
"2 Days 03h 42m 07s", try this:
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;
}

After wading through all the other answers, to keep the Java 7 Date type but be more precise/standard with the Java 8 diff approach,
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;
}

Note: startDate and endDates are -> java.util.Date
import org.joda.time.Duration;
import org.joda.time.Interval;
// Use .getTime() unless it is a joda DateTime object
Interval interval = new Interval(startDate.getTime(), endDate.getTime());
Duration period = interval.toDuration();
//gives the number of days elapsed between start and end date.
period.getStandardDays();
Similar to days, you can also get hours, minutes and seconds
period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();

Check example here http://www.roseindia.net/java/beginners/DateDifferent.shtml
This example give you difference in days, hours, minutes, secs and milli sec's :).
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.");
}
}

Use GMT time zone to get an instance of the Calendar, set the time using the set method of Calendar class. The GMT timezone has 0 offset (not really important) and daylight saving time flag set to 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));

Following code can give you the desired output:
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());

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";
}
}

Best thing to do is
(Date1-Date2)/86 400 000
That number is the number of milliseconds in a day.
One date-other date gives you difference in milliseconds.
Collect the answer in a double variable.

Here's a correct Java 7 solution in O(1) without any dependencies.
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;
}

That's probably the most straightforward way to do it - perhaps it's because I've been coding in Java (with its admittedly clunky date and time libraries) for a while now, but that code looks "simple and nice" to me!
Are you happy with the result being returned in milliseconds, or is part of your question that you would prefer to have it returned in some alternative format?

Not using the standard API, no. You can roll your own doing something like this:
class Duration {
private final TimeUnit unit;
private final long length;
// ...
}
Or you can use Joda:
DateTime a = ..., b = ...;
Duration d = new Duration(a, b);

Just to answer the initial question:
Put the following code in a Function like 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;
The most important here is to work with long numbers when multiplying and dividing. And of course, the offset that Java applies in its calculus of Dates.
:)

Since the question is tagged with 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

If you want to fix the issue for date ranges that cross daylight savings time boundary (e.g. one date in summer time and the other one in winter time), you can use this to get the difference in days:
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);
}

Related

how to calculate and split a float value into two separate integer values ?? e.g 18.5f hours equals int h=18 int m=30

I am creating a Workday calendar program that calculates a 'start' and 'end' date
the results should output:
"Starting date: 24-05-2004 07:03 with addition of 8.276628 working days is end date: 04-06-2004 10:12"
or
24-05-2004 18:03 with the addition of -6.7470217 working days is 13-05-2004 10:02
The mathematical solution is to multiply hours pr day with incrementInWokringdays
like 8.0f hours a day * 2.5f days = 18.4f hours and then the result of this should be added to the Date calendar this way
-date.add( Calendar.Hours_of_Day, 18.0f ) //but from float converted to integers
-date.add( Calendar.Minutes_of_Day, 0.4f )//
how do i split the value 18.4f hours in to
'int hours = 18;'
and
'int minutes = 40;'
????
public Date getWorkdayIncrement(Calendar date, float incrementInWorkdays) {
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm");
System.out.println("start day: " + f.format(date.getTime()));
// so if chosen incrementDays is 2.3 days and workinghours pr day is 7.5h you multiply them together to get total working hours
float totalHoursWorkedPrDay = getWorkdayStartAndStop() * incrementInWorkdays;
// needed to convert hours and minutes to integer values in order to increment calendar
int hoursToIncrement = (int) totalHoursWorkedPrDay; //gets only hours
// get the last to decimals 0.25 representing the minutes which means 25 percent of 60min
float lastTwoDecimalsOfTotalWorkingHours = ((totalHoursWorkedPrDay - (float) hoursToIncrement) * 100);
//calculate percent of minutes and convert to integer (25 / 100 * 60) = 15min
int minutesToIncrement = (int) ((lastTwoDecimalsOfTotalWorkingHours / 100) *60);
System.out.println("Hours to increment: " + hoursToIncrement);
System.out.println("Minutes to increment: " + minutesToIncrement);
//increment calendar
date.add(Calendar.HOUR_OF_DAY, hoursToIncrement);
date.add(Calendar.MINUTE, minutesToIncrement);
Date endDate = date.getTime();
System.out.println("End date excluding holidays: " + f.format(endDate));
}
I didn’t follow everything you were doing in the question. So for now I focus on calculating the working hours of a working day given start and end time. I am assuming that you get start and end as GregorianCalendar objects from some legacy API that you cannot afford to upgrade to java.time just now.
I recommend that you use java.time, the modern Java date and time API, for your date and time work. Even if you are getting your data as objects of the old-fashioned date-time types. java.time is so much nicer to work with.
static float getHoursBetween(Calendar start, Calendar end) {
ZonedDateTime startZdt = ((GregorianCalendar) start).toZonedDateTime();
ZonedDateTime endZdt = ((GregorianCalendar) end).toZonedDateTime();
long wholeDays = ChronoUnit.DAYS.between(startZdt, endZdt);
startZdt = startZdt.plusDays(wholeDays);
Duration workDay = Duration.between(startZdt, endZdt);
return (float) workDay.toMinutes() / (float) Duration.ofHours(1).toMinutes();
}
The method ignores the date difference between start and end by adding the number of full days to the start time. This means that the result we get is based only on the hours and minutes. To try the method out, let’s construct a couple of GregorianCalendar objects (of course I am using java.time for that too):
ZoneId zone = ZoneId.of("America/Araguaina");
ZonedDateTime workDayStart = ZonedDateTime.of(2020, 6, 14, 7, 30, 0, 0, zone);
Calendar workDayStartCal = GregorianCalendar.from(workDayStart);
ZonedDateTime workDayEnd = ZonedDateTime.of(2020, 6, 15, 15, 15, 0, 0, zone);
Calendar workDayEndCal = GregorianCalendar.from(workDayEnd);
float workingDay = getHoursBetween(workDayStartCal, workDayEndCal);
System.out.println(workingDay);
Output from the example is:
7.75
Edit: for the opposite conversion this works since Java 9:
float hours = 7.75f;
Duration dur = Duration.ofMinutes(Math.round(hours * Duration.ofHours(1).toMinutes()));
System.out.println("Hours: " + dur.toHours());
System.out.println("Minutes: " + dur.toMinutesPart());
Hours: 7
Minutes: 45
Link
Oracle tutorial: Date Time explaining how to use java.time.

Java Android: how to compare current time to a calculated time? [duplicate]

I'm using Java's java.util.Date class in Scala and want to compare a Date object and the current time. I know I can calculate the delta by using getTime():
(new java.util.Date()).getTime() - oldDate.getTime()
However, this just leaves me with a long representing milliseconds. Is there any simpler, nicer way to get a time delta?
Simple diff (without lib)
/**
* 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);
}
And then can you call:
getDateDiff(date1,date2,TimeUnit.MINUTES);
to get the diff of the 2 dates in minutes unit.
TimeUnit is java.util.concurrent.TimeUnit, a standard Java enum going from nanos to days.
Human readable diff (without lib)
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;
}
http://ideone.com/5dXeu6
The output is something like Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}, with the units ordered.
You just have to convert that map to a user-friendly string.
Warning
The above code snippets compute a simple diff between 2 instants. It can cause problems during a daylight saving switch, like explained in this post. This means if you compute the diff between dates with no time you may have a missing day/hour.
In my opinion the date diff is kind of subjective, especially on days. You may:
count the number of 24h elapsed time: day+1 - day = 1 day = 24h
count the number of elapsed time, taking care of daylight savings: day+1 - day = 1 = 24h (but using midnight time and daylight savings it could be 0 day and 23h)
count the number of day switches, which means day+1 1pm - day 11am = 1 day, even if the elapsed time is just 2h (or 1h if there is a daylight saving :p)
My answer is valid if your definition of date diff on days match the 1st case
With JodaTime
If you are using JodaTime you can get the diff for 2 instants (millies backed ReadableInstant) dates with:
Interval interval = new Interval(oldInstant, new Instant());
But you can also get the diff for Local dates/times:
// 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()
The JDK Date API is horribly broken unfortunately. I recommend using Joda Time library.
Joda Time has a concept of time Interval:
Interval interval = new Interval(oldTime, new Instant());
EDIT: By the way, Joda has two concepts: Interval for representing an interval of time between two time instants (represent time between 8am and 10am), and a Duration that represents a length of time without the actual time boundaries (e.g. represent two hours!)
If you only care about time comparisions, most Date implementations (including the JDK one) implements Comparable interface which allows you to use the Comparable.compareTo()
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime())
/ (1000 * 60 * 60 * 24) )
Note that this works with UTC dates, so the difference may be a day off if you look at local dates. And getting it to work correctly with local dates requires a completely different approach due to daylight savings time.
Using the java.time framework built into 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());
Output:
ISO-8601: PT24H10M
Minutes: 1450
For more info, see the Oracle Tutorial and the ISO 8601 standard.
tl;dr
Convert your obsolete java.util.Date objects to their replacement, java.time.Instant. Then calculate the elapsed time as a 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
ISO 8601 Format: PnYnMnDTnHnMnS
The sensible standard ISO 8601 defines a concise textual representation of a span of time as a number of years, months, days, hours, etc. The standard calls such such a span a duration. The format is PnYnMnDTnHnMnS where the P means "Period", the T separates the date portion from the time portion, and in between are numbers followed by a letter.
Examples:
P3Y6M4DT12H30M5Sthree years, six months, four days, twelve hours, thirty minutes, and five seconds
PT4H30MFour and a half hours
java.time
The java.time framework built into Java 8 and later supplants the troublesome old java.util.Date/java.util.Calendar classes. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
Moment
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now() ; // Capture current moment in UTC.
Best to avoid the legacy classes such as Date/Calendar. But if you must inter-operate with old code not yet updated to java.time, convert back and forth. Call new conversion methods added to the old classes. For moving from a java.util.Date to an Instant, call Date::toInstant.
Instant instant = myJavaUtilDate.toInstant() ; // Convert from legacy `java.util.Date` class to modern `java.time.Instant` class.
Span of time
The java.time classes have split this idea of representing a span of time as a number of years, months, days, hours, minutes, seconds into two halves:
Period for years, months, days
Duration for days, hours, minutes, seconds
Here is an example.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );
Dump to console.
Both Period and Duration use the ISO 8601 standard for generating a String representation of their value.
System.out.println ( "now: " + now + " to future: " + now + " = " + duration );
now: 2015-11-26T00:46:48.016-05:00[America/Montreal] to future: 2015-11-26T00:46:48.016-05:00[America/Montreal] = PT1H3M
Java 9 adds methods to Duration to get the days part, hours part, minutes part, and seconds part.
You can get the total number of days or hours or minutes or seconds or milliseconds or nanoseconds in the entire Duration.
long totalHours = duration.toHours();
In Java 9 the Duration class gets new methods for returning the various parts of days, hours, minutes, seconds, milliseconds/nanoseconds. Call the to…Part methods: toDaysPart(), toHoursPart(), and so on.
ChronoUnit
If you only care about a simpler larger granularity of time, such as “number of days elapsed”, use the ChronoUnit enum.
long daysElapsed = ChronoUnit.DAYS.between( earlier , later );
Another example.
Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );
…
long minutesElapsed = ChronoUnit.MINUTES.between( now , later );
120
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Joda-Time
UPDATE: The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. I leave this section intact for history.
The Joda-Time library uses ISO 8601 for its defaults. Its Period class parses and generates these PnYnMnDTnHnMnS strings.
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
You need to define your problem more clearly. You could just take the number of milliseconds between the two Date objects and divide by the number of milliseconds in 24 hours, for example... but:
This won't take time zones into consideration - Date is always in UTC
This won't take daylight saving time into consideration (where there can be days which are only 23 hours long, for example)
Even within UTC, how many days are there in August 16th 11pm to August 18th 2am? It's only 27 hours, so does that mean one day? Or should it be three days because it covers three dates?
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();
https://www.joda.org/joda-time/faq.html#datediff
A slightly simpler alternative:
System.currentTimeMillis() - oldDate.getTime()
As for "nicer": well, what exactly do you need? The problem with representing time durations as a number of hours and days etc. is that it may lead to inaccuracies and wrong expectations due to the complexity of dates (e.g. days can have 23 or 25 hours due to daylight savings time).
Using millisecond approach can cause problems in some locales.
Lets take, for example, the difference between the two dates 03/24/2007 and 03/25/2007 should be 1 day;
However, using the millisecond route, you'll get 0 days, if you run this in the UK!
/** 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);
}
Better way to implement this is to use 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;
}
Since all the answers here are correct but use legacy java or 3rd party libs like joda or similar, I will just drop another way using new java.time classes in Java 8 and later. See Oracle Tutorial.
Use LocalDate and 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 );
There are many ways you can find the difference between dates & times. One of the simplest ways that I know of would be:
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);
The print statement is just an example - you can format it, the way you like.
If you don't want to use JodaTime or similar, the best solution is probably this:
final static long MILLIS_PER_DAY = 24 * 3600 * 1000;
long msDiff= date1.getTime() - date2.getTime();
long daysDiff = Math.round(msDiff / ((double)MILLIS_PER_DAY));
The number of ms per day is not always the same (because of daylight saving time and leap seconds), but it's very close, and at least deviations due to daylight saving time cancel out over longer periods. Therefore dividing and then rounding will give a correct result (at least as long as the local calendar used does not contain weird time jumps other than DST and leap seconds).
Note that this still assumes that date1 and date2 are set to the same time of day. For different times of day, you'd first have to define what "date difference" means, as pointed out by Jon Skeet.
Subtracting the dates in milliseconds works (as described in another post), but you have to use HOUR_OF_DAY and not HOUR when clearing the time parts of your 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
}
Take a look at Joda Time, which is an improved Date/Time API for Java and should work fine with Scala.
int daysDiff = (date1.getTime() - date2.getTime()) / MILLIS_PER_DAY;
Let me show difference between Joda Interval and 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
If you need a formatted return String like
"2 Days 03h 42m 07s", try this:
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;
}
After wading through all the other answers, to keep the Java 7 Date type but be more precise/standard with the Java 8 diff approach,
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;
}
Note: startDate and endDates are -> java.util.Date
import org.joda.time.Duration;
import org.joda.time.Interval;
// Use .getTime() unless it is a joda DateTime object
Interval interval = new Interval(startDate.getTime(), endDate.getTime());
Duration period = interval.toDuration();
//gives the number of days elapsed between start and end date.
period.getStandardDays();
Similar to days, you can also get hours, minutes and seconds
period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();
Check example here http://www.roseindia.net/java/beginners/DateDifferent.shtml
This example give you difference in days, hours, minutes, secs and milli sec's :).
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.");
}
}
Use GMT time zone to get an instance of the Calendar, set the time using the set method of Calendar class. The GMT timezone has 0 offset (not really important) and daylight saving time flag set to 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));
Following code can give you the desired output:
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());
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";
}
}
Best thing to do is
(Date1-Date2)/86 400 000
That number is the number of milliseconds in a day.
One date-other date gives you difference in milliseconds.
Collect the answer in a double variable.
Here's a correct Java 7 solution in O(1) without any dependencies.
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;
}
That's probably the most straightforward way to do it - perhaps it's because I've been coding in Java (with its admittedly clunky date and time libraries) for a while now, but that code looks "simple and nice" to me!
Are you happy with the result being returned in milliseconds, or is part of your question that you would prefer to have it returned in some alternative format?
Not using the standard API, no. You can roll your own doing something like this:
class Duration {
private final TimeUnit unit;
private final long length;
// ...
}
Or you can use Joda:
DateTime a = ..., b = ...;
Duration d = new Duration(a, b);
Just to answer the initial question:
Put the following code in a Function like 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;
The most important here is to work with long numbers when multiplying and dividing. And of course, the offset that Java applies in its calculus of Dates.
:)
Since the question is tagged with 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
If you want to fix the issue for date ranges that cross daylight savings time boundary (e.g. one date in summer time and the other one in winter time), you can use this to get the difference in days:
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);
}

Java calculating time with timestamps [duplicate]

This question already has answers here:
Calculating the difference between two Java date instances
(45 answers)
Closed 7 years ago.
Im trying to calculate the time difference between 2 Timestamps, this is the code:
Calendar calendar = Calendar.getInstance();
java.util.Date now = calendar.getTime();
Timestamp currentTimestamp = new Timestamp(now.getTime());
System.out.println("Current\n"+currentTimestamp);
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
Date date = dateFormat.parse("28/02/2015");
Timestamp timestampBefore = new Timestamp(date.getTime());
System.out.println("Before\n"+timestampBefore);
Timestamp calculated = new Timestamp(currentTimestamp.getTime() - timestampBefore.getTime());
System.out.println("Calculated\n"+calculated);
Output:
Current
2015-02-28 12:12:40.975
Before
2015-02-28 00:00:00.0
Calculated
1970-01-01 13:12:40.975
I can understand why it returns 1970-01-01 but why does it return 13:12:40.975 ,1 hour more?
How to calculate the difference between 2 dates so the output is like this (based on this example):
Years:0, Months:0, Days:0, Hours:12, Minutes:12, Seconds:40 ?
Update: for java below 1.8 check out http://www.joda.org/joda-time/index.html
and for java 1.8 see answer.
Similar solution here: Java 8: Calculate difference between two LocalDateTime
(1) A timestamp is a point in time. If you calculate the difference between two timestamps, the result is not a timestamp (point in time), but a duration. So it is nonsense to convert the difference to a timestamp, hence it is useless to discuss the reason why the result is strange.
(2) You should probably use the new Java 8 time API (if you are able to use Java 8):
LocalTime now = LocalTime.now();
LocalTime previous = LocalTime.of(0, 0, 0, 0);
Duration duration = Duration.between(previous, now);
System.out.println(now);
System.out.println(previous);
System.out.println(duration);
Note that this just calculates the duration between two times of a day (hour-minute-second). If your want to include date information, use LocalDateTime instead:
LocalDateTime nextFirework = LocalDate.now()
.with(TemporalAdjusters.firstDayOfNextYear())
.atTime(LocalTime.MIDNIGHT);
LocalDateTime now = LocalDateTime.now();
// duration (in seconds and nanos)
Duration duration = Duration.between(now, nextFirework);
// duration in total hours
long hours = now.until(nextFirework, ChronoUnit.HOURS);
// equals to: duration.toHours();
If you want to have 'normalized' duration in years/months/days/hours/seconds, there is suprisingly no direct support. You could convert the duration to days, hours, minutes and seconds by yourself:
long d = duration.toDays();
long h = duration.toHours() - 24 * d;
long m = duration.toMinutes() - 60 * duration.toHours();
long s = duration.getSeconds() - 60 * duration.toMinutes();
System.out.println(d + "d " + h + "h " + m + "m " + s + "s ");
But note that you will have difficulties converting the days into months and years, as there is no unique number of days per month and a year can be a leap year with 366 days. For that, you can use Period, as in opposite to Duration, this class is associated with a timeline. Unfortunately, Period does only support dates, but no times:
// period in years/months/days (ignoring time information)
Period p = Period.between(now.toLocalDate(), nextFirework.toLocalDate());
System.out.println(p); // or use p.getYears(), p.getMonths(), p.getDays()
So probably you could combine both approaches - first, compute the Period from the dates and then the Duration using the times. Note that the duration can be negative, so you'll have to take care of that in case of:
Duration dur = Duration.between(start.toLocalTime(), end.toLocalTime());
LocalDate e = end.toLocalDate();
if (dur.isNegative()) {
dur = dur.plusDays(1);
e = e.minusDays(1);
}
Period per = Period.between(start.toLocalDate(), e);
System.out.println(per.toString() + ", " + dur.toString());

Android Days between two dates

I want to compare two dates for my Android application, but I got a really weird issue.
For example:
If I set the back in the past date to 127 days ago:
this.dateEvent = System.currentTimeMillis() - (127 * 24 * 3600 * 1000)
And then compare it to the current date (Days between)
Calendar sDate = getDatePart(new Date(this.dateEvent));
Calendar eDate = getDatePart(new Date(System.currentTimeMillis()));
int daysBetween = 0;
while (sDate.before(eDate))
{
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween ++;
}
while (sDate.after(eDate))
{
eDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween ++;
}
return daysBetween;
It will return 22 which is not at all what was expected.
Did I make something wrong or is that an issue with the Calendar class ?
Here's a two line solution:
long msDiff = Calendar.getInstance().getTimeInMillis() - testCalendar.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);
In this example it gets the number of days between date "testCalendar" and the current date.
Please refer this code, this may help you.
public String getCountOfDays(String createdDateString, String expireDateString) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());
Date createdConvertedDate = null, expireCovertedDate = null, todayWithZeroTime = null;
try {
createdConvertedDate = dateFormat.parse(createdDateString);
expireCovertedDate = dateFormat.parse(expireDateString);
Date today = new Date();
todayWithZeroTime = dateFormat.parse(dateFormat.format(today));
} catch (ParseException e) {
e.printStackTrace();
}
int cYear = 0, cMonth = 0, cDay = 0;
if (createdConvertedDate.after(todayWithZeroTime)) {
Calendar cCal = Calendar.getInstance();
cCal.setTime(createdConvertedDate);
cYear = cCal.get(Calendar.YEAR);
cMonth = cCal.get(Calendar.MONTH);
cDay = cCal.get(Calendar.DAY_OF_MONTH);
} else {
Calendar cCal = Calendar.getInstance();
cCal.setTime(todayWithZeroTime);
cYear = cCal.get(Calendar.YEAR);
cMonth = cCal.get(Calendar.MONTH);
cDay = cCal.get(Calendar.DAY_OF_MONTH);
}
/*Calendar todayCal = Calendar.getInstance();
int todayYear = todayCal.get(Calendar.YEAR);
int today = todayCal.get(Calendar.MONTH);
int todayDay = todayCal.get(Calendar.DAY_OF_MONTH);
*/
Calendar eCal = Calendar.getInstance();
eCal.setTime(expireCovertedDate);
int eYear = eCal.get(Calendar.YEAR);
int eMonth = eCal.get(Calendar.MONTH);
int eDay = eCal.get(Calendar.DAY_OF_MONTH);
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
date1.clear();
date1.set(cYear, cMonth, cDay);
date2.clear();
date2.set(eYear, eMonth, eDay);
long diff = date2.getTimeInMillis() - date1.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
return ("" + (int) dayCount + " Days");
}
I've finally found the easiest way to deal with that. Here is my code:
public int getTimeRemaining()
{
Calendar sDate = toCalendar(this.dateEvent);
Calendar eDate = toCalendar(System.currentTimeMillis());
// Get the represented date in milliseconds
long milis1 = sDate.getTimeInMillis();
long milis2 = eDate.getTimeInMillis();
// Calculate difference in milliseconds
long diff = Math.abs(milis2 - milis1);
return (int)(diff / (24 * 60 * 60 * 1000));
}
private Calendar toCalendar(long timestamp)
{
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar;
}
Hope it helps.
You should never use formula such 24 * 60 * 60 * 1000! Why? Because there is day saving time, and not all days have 24 hours, also what about leap year, that has +1 day. That's why there is a calendar class.
If you do not want to put any external library to your project like Jodatime, you could use pure Calendar class with very efficient function:
public static int numDaysBetween(final Calendar c, final long fromTime, final long toTime) {
int result = 0;
if (toTime <= fromTime) return result;
c.setTimeInMillis(toTime);
final int toYear = c.get(Calendar.YEAR);
result += c.get(Calendar.DAY_OF_YEAR);
c.setTimeInMillis(fromTime);
result -= c.get(Calendar.DAY_OF_YEAR);
while (c.get(Calendar.YEAR) < toYear) {
result += c.getActualMaximum(Calendar.DAY_OF_YEAR);
c.add(Calendar.YEAR, 1);
}
return result;
}
public long Daybetween(String date1,String date2,String pattern)
{
SimpleDateFormat sdf = new SimpleDateFormat(pattern,Locale.ENGLISH);
Date Date1 = null,Date2 = null;
try{
Date1 = sdf.parse(date1);
Date2 = sdf.parse(date2);
}catch(Exception e)
{
e.printStackTrace();
}
return (Date2.getTime() - Date1.getTime())/(24*60*60*1000);
}
Date userDob = new SimpleDateFormat("yyyy-MM-dd").parse(dob);
Date today = new Date();
long diff = today.getTime() - userDob.getTime();
int numOfYear = (int) ((diff / (1000 * 60 * 60 * 24))/365);
int numOfDays = (int) (diff / (1000 * 60 * 60 * 24));
int hours = (int) (diff / (1000 * 60 * 60));
int minutes = (int) (diff / (1000 * 60));
int seconds = (int) (diff / (1000));
I had the same need, I finally ended up using Joda Time, it is very convenient and offers lots of additional functions including the one you are looking for.
You can download the files from here.
Once you included the jar file into your project, you can easily do for example the following:
int daysBetween = Days.daysBetween(new DateTime(sDate), new DateTime(eDate)).getDays();
the best way :-
long fromCalender = Calender.getInstance();
fromCalender.set...// set the from dates
long toCalender = Calender.getInstance();
fromCalender.set...// set the to dates
long diffmili = fromCalender - toCalender;
long hours = TimeUnit.MILLISECONDS.toHours(diffmili);
long days = TimeUnit.MILLISECONDS.toDays(diffmili);
long min = TimeUnit.MILLISECONDS.toMinutes(diffmili);
long sec = TimeUnit.MILLISECONDS.toSeconds(diffmili);
Do like this it supports all Api Levels
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm:ss",
Locale.ENGLISH);
try {
String datestart="June 14 2018 16:02:37";
cal.setTime(sdf.parse(datestart));// all done
Calendar cal1=Calendar.getInstance();
String formatted = sdf.format(cal1.getTime());//formatted date as i want
cal1.setTime(sdf.parse(formatted));// all done
long msDiff = cal1.getTimeInMillis() - cal.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);
Toast.makeText(this, "days="+daysDiff, Toast.LENGTH_SHORT).show();
} catch (ParseException e) {
e.printStackTrace();
}
fun TimeZone.daysBetween(from: Date, to: Date): Int {
val offset = rawOffset + dstSavings
return ((to.time + offset) / 86400000).toInt() - ((from.time + offset) / 86400000).toInt()
}
Have a try:
val f = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
timeZone = TimeZone.getTimeZone("GMT")
}
val df = f.parse("2019-02-28 22:59:59")
val dt = f.parse("2019-02-28 23:00:00")
TimeZone.getTimeZone("GMT").daysBetween(df, dt) // 0
TimeZone.getTimeZone("GMT+1").daysBetween(df, dt) // 1
java.time and ThreeTenABP
I should like to contribute the modern answer: Use java.time, the modern Java date and time API for your date work. If developing for Android API level 25 or lower, then through the backport for Android, ThreeTenABP (link at the bottom).
LocalDate eDate = LocalDate.now(ZoneId.of("Europe/Paris"));
LocalDate sDate = eDate.minusDays(127);
long daysBetween = ChronoUnit.DAYS.between(sDate, eDate);
System.out.println(daysBetween);
When I ran this code today, the output was the expected:
127
Notice that the code is not only shorter, just one line for finding the difference; it is also clearer and more natural to read. The classes Date and Calendar that you used are poorly designed and long outdated. I recommend you don’t use them.
What went wrong in your code?
You’ve got an int overflow in your conversion of 127 days to milliseconds. In mathematics 127 * 24 * 3600 * 1000 equals 10 972 800 000. Since the numbers you multiply are ints, Java performs the multiplication in int, and the largest number an int can hold is 2 147 483 647, far from enough for your expected result. In this situation it would have been nice if Java would have thrown an exception or in some other way have made us aware of the error. It doesn’t. It tacitly throws away the high order bits, giving us a result of -1 912 101 888. Subtracting this negative number from the current time is equivalent to adding 22 days and a few hours. This explains why you got 22. Funny that 13 answers have been posted and it seems that no one has spotted this …
Even when doing the multiplication using the long type, it still doesn’t calculate 127 days correctly, though. If the 127 days cross a transition to or from summer time (DST), which in France is the case during 254 of the 365 days of a year, the day of the transition is not 24 hours, but either 23 or 25. Which causes an incorrect number of milliseconds.
You should always leave date math to proven library methods. Never hand code it yourself. It’s more complicated than most of us think, so the risk of doing it incorrectly is high.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
The best solution that worked for me is :
private static int findDaysDiff(long unixStartTime,long unixEndTime)
{
Calendar calendar1 = Calendar.getInstance();
calendar1.setTimeInMillis(unixStartTime);
calendar1.set(Calendar.HOUR_OF_DAY, 0);
calendar1.set(Calendar.MINUTE, 0);
calendar1.set(Calendar.SECOND, 0);
calendar1.set(Calendar.MILLISECOND, 0);
Calendar calendar2 = Calendar.getInstance();
calendar2.setTimeInMillis(unixEndTime);
calendar2.set(Calendar.HOUR_OF_DAY, 0);
calendar2.set(Calendar.MINUTE, 0);
calendar2.set(Calendar.SECOND, 0);
calendar2.set(Calendar.MILLISECOND, 0);
return (int) ((calendar2.getTimeInMillis()-calendar1.getTimeInMillis())/(24 * 60 * 60 * 1000));
}
Since it first converts Hour , Minute, Second and Millisecond to 0 and now the difference will be only in days.
the answer is not correct in some dates like "2019/02/18" , "2019/02/19" but i edit and resolve bug
this is best method :
public int getCountOfDays(String createdDateString, String expireDateString) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date createdConvertedDate = null;
Date expireCovertedDate = null;
try {
createdConvertedDate = dateFormat.parse(createdDateString);
expireCovertedDate = dateFormat.parse(expireDateString);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar start = new GregorianCalendar();
start.setTime(createdConvertedDate);
Calendar end = new GregorianCalendar();
end.setTime(expireCovertedDate);
long diff = end.getTimeInMillis() - start.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
return (int) (dayCount);
}
Enjoy and if was helpefull +vote to this answer ;)
Kotlin Extension:
fun Date?.getDaysBetween(dest: Date?): Int {
if(this == null || dest == null) return 0
val diff = abs(this.time - dest.time)
val dayCount = diff.toFloat() / (24 * 60 * 60 * 1000)
return dayCount.toInt()
}
I am count the days between last submission date and current date if it is less than zero then student cannot give submission. I am working with kotlin. The below code helps you.
var calendar=Calendar.getInstance().time
var dateFormat= SimpleDateFormat("dd/M/yyyy")
var d2=dateFormat.parse(data.get("date").toString())
var cd=dateFormat.format(calendar)
var d1=dateFormat.parse(cd)
var diff=d2.time-d1.time
var ddd= TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)
This is the Java 8 java.time version which works perfectly for me. You might want to make sure that startDate and endDate are set to the same time, otherwise days might vary by +-1!
These are the Kotlin versions I just copy/pasted.
private fun getDawnOfDay(instant: Instant): Temporal =
LocalDate.from(instant.atZone(ZoneOffset.UTC)).atStartOfDay()
fun getNumberOfDaysInBetween(startDate: Date, endDate: Date) =
Duration.between(getDawnOfDay(startDate.toInstant()), getDawnOfDay(endDate.toInstant()))
.toDays()
I have just modified a little bit most popular answer.
Here is my solution:
daysBetween() - Return days count between two dates.
public static long daysBetween(Date date1, Date date2) {
long msDiff = resetTimeToDateStart(date1).getTime() - resetTimeToDateStart(date2).getTime();
return TimeUnit.MILLISECONDS.toDays(msDiff);
}
private static Date resetTimeToDateStart(Date dDate){
if (Utils.isNull(dDate)){
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(dDate);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
int difference in days=(present_year - oldyear) * 365 + (present_month - oldmonth)*30 + (present_date-olddate);
All above answers calculating millis_diff / (24 * 60 * 60 * 1000) is simply wrong if you consider 23:59:59 ~ 00:00:00 as two different days and expect offset day count as 1, instead of 0.
A kotlin version gives you count 1, based on #oleksandr-albul answer above.
fun getDayCountBetween(to: Long, from: Long): Int {
if (to <= from) return 0
val calendar = Calendar.getInstance()
var count = 0
// get day count between 'to' and Jan 1st.
calendar.timeInMillis = to
val year = calendar.get(Calendar.YEAR)
count += calendar.get(Calendar.DAY_OF_YEAR)
// minus day count between 'from' and Jan 1st.
calendar.timeInMillis = from
count -= calendar.get(Calendar.DAY_OF_YEAR)
// plus day count of all the gap years.
while (calendar.get(Calendar.YEAR) < year) {
count += calendar.getActualMaximum(Calendar.DAY_OF_YEAR)
calendar.add(Calendar.YEAR, 1)
}
return count
}

Get the number of weeks between two Dates.

Im working in a project and I got two types in Date. I want to calculate the number of weeks between these two dates. The dates can be in diffrent years. Is there any good solution for this?
I have tried to implemenent this with Joda-time which was suggested in other topics..
Im not familar with this library, but I tried to do something like this:
public static int getNumberOfWeeks(Date f, Date l){
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.setTime(f);
c2.setTime(l);
DateTime start = new DateTime(c1.YEAR, c1.MONTH, c1.DAY_OF_MONTH, 0, 0, 0, 0);
DateTime end = new DateTime(c2.YEAR, c2.MONTH, c2.DAY_OF_MONTH, 0, 0, 0, 0);
Interval interval = new Interval(start, end);
Period p = interval.toPeriod();
return p.getWeeks();
}
But this is completely wrong... any suggestions ?
Updating answer to account for Java 8
// TechTrip - ASSUMPTION d1 is earlier than d2
// leave that for exercise
public static long getFullWeeks(Calendar d1, Calendar d2){
Instant d1i = Instant.ofEpochMilli(d1.getTimeInMillis());
Instant d2i = Instant.ofEpochMilli(d2.getTimeInMillis());
LocalDateTime startDate = LocalDateTime.ofInstant(d1i, ZoneId.systemDefault());
LocalDateTime endDate = LocalDateTime.ofInstant(d2i, ZoneId.systemDefault());
return ChronoUnit.WEEKS.between(startDate, endDate);
}
It is pretty easy with joda time:
DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);
int weeks = Weeks.weeksBetween(dateTime1, dateTime2).getWeeks();
tl;dr
ChronoUnit
.WEEKS
.between(
myJavaUtilDate_Start.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) ) ,
myJavaUtilDate_Stop.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) )
)
7
java.time
The java.time framework is built into Java 8 and later. These new classes supplant the old date-time classes bundled with the earliest versions of Java.
The java.time classes also supplant the highly successful Joda-Time framework. Both java.time and Joda-Time are led by Stephen Colbourne.
Instant replaces java.util.Date
The modern class Instant replaces the legacy class java.util.Date. Both represent a moment in UTC, a specific point on the timeline. Both internally use a count since the same epoch reference of the first moment of 1970 in UTC, 1970-01-01T00:00Z. The old class uses a count of milliseconds, while Instant uses a finer count of nanoseconds.
To convert, call new methods added to the old classes.
Instant start = myJavaUtilDateStart.toInstant() ;
Instant stop = myJavaUtilDateStop.toInstant() ;
Let's make this concrete with some example values.
Instant start = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).toInstant();
Instant stop = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).plusWeeks(7 ).toInstant();
Moments versus dates
Both of our Instant objects represent a moment. The goal is a count of weeks. Weeks means days, and days mean certain dates on the calendar.
So we have a bit of a mismatch. For any given moment, the date varies around the globe by time zone. A few minutes after midnight in Paris France is a new date. Meanwhile in Montréal Québec, being several hours behind, that same moment is still “yesterday”, the date before on the calendar. So we cannot directly calculate weeks from a pair of moments.
You must first decide on the time zone by which you want to perceive a calendar for those moments.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime
Apply this ZoneId to our Instant objects to adjust into a time zone, yielding a pair of ZonedDateTime objects.
ZonedDateTime startZdt = start.atZone( z ) ;
ZonedDateTime stopZdt = stop.atZone( z ) ;
ChronoUnit.WEEKS
Now we can use the ChronoUnit enum to calculate elapsed weeks.
long weeks = ChronoUnit.WEEKS.between( startZdt , stopZdt );
Dump to console.
System.out.println( "start.toString() = " + start );
System.out.println( "stop.toString() = " + stop );
System.out.println( "startZdt.toString() = " + startZdt );
System.out.println( "stopZdt.toString() = " + stopZdt );
System.out.println( "weeksCount: " + weeksCount );
See this code run live at IdeOne.com.
start.toString() = 2020-01-23T15:30:00Z
stop.toString() = 2020-03-12T15:30:00Z
startZdt.toString() = 2020-01-23T10:30-05:00[America/Montreal]
stopZdt.toString() = 2020-03-12T11:30-04:00[America/Montreal]
weeksCount: 7
ThreeTen-Extra
The ThreeTen-Extra project adds functionality to the java.time framework built into Java 8 and later.
Weeks class
That project includes a Weeks class to represent a number of weeks. Not only can it calculate, it is also meant to be used in your code as a type-safe object. Such use also helps to make your code self-documenting.
You can instantiate by providing a pair of points in time with the Weeks.between method. Those points in time can be anything implementing java.time.temporal.Temporal including Instant, LocalDate, OffsetDateTime, ZonedDateTime, Year, YearMonth, and more.
Your java.util.Date objects can be easily converted to Instant objects, moments on the timeline in UTC with a resolution in nanoseconds. Look at new methods added to the old date-time classes. For going from Date to Instant, call java.util.Date::toInstant.
Weeks weeks = Weeks.between( startZdt , stopZdt );
You can ask for the number of weeks.
int weeksNumber = weeks.getAmount(); // The number of weeks in this Weeks object.
You can also do much more.
Generate a string in standard ISO 8601 format. The P marks the beginning. The W indicates a number of weeks.
PW7
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Using the date arithmetic in java.util.Calendar:
public static int getWeeksBetween (Date a, Date b) {
if (b.before(a)) {
return -getWeeksBetween(b, a);
}
a = resetTime(a);
b = resetTime(b);
Calendar cal = new GregorianCalendar();
cal.setTime(a);
int weeks = 0;
while (cal.getTime().before(b)) {
// add another week
cal.add(Calendar.WEEK_OF_YEAR, 1);
weeks++;
}
return weeks;
}
public static Date resetTime (Date d) {
Calendar cal = new GregorianCalendar();
cal.setTime(d);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
If your requirement is like the start date is 03-Apr-2020 and end date is 07-Apr-2020. the difference between the two dates is 4 days. Now the number of weeks between two dates as 1 for this you can use below snippet.
ChronoUnit.WEEKS.between(LocalDate startDate, LocalDate endDate);
But If your requirement is like 03-Apr-2020 is in one week and 07-Apr-2020 is in another week so you want the number of weeks between two dates as 2 you can use the below snippet.
LocalDate actualStartDate=...
LocalDate actualEndDate=...
LocalDate startDate = actualStartDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY))
LocalDate endDate = actualEndDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SATURDAY))
long daysBetweenTwoDates = ChronoUnit.DAYS.between(startDate, endDate);
int numberOfWeeks = (int)Math.ceil(daysBetweenTwoDates/7.0);
Tested in java 1.8
Calendar a = new GregorianCalendar(2002,1,22);
Calendar b = new GregorianCalendar(2002,1,28);
System.out.println(a.get(Calendar.WEEK_OF_YEAR));
System.out.println(b.get(Calendar.WEEK_OF_YEAR));
int weeks = b.get(Calendar.WEEK_OF_YEAR)-a.get(Calendar.WEEK_OF_YEAR);
System.out.println(weeks);
try this must work
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.set(2007, 01, 10);
calendar2.set(2007, 07, 01);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
int diffWeeks = (int)diff / (7*24 * 60 * 60 * 1000);
Here are 2 methods I wrote that not based on an external library.
The first method is when Monday is the first day of the week.
The second method is when Sunday is the first day of the week.
Please read the comments inside the code, there is an option to return the number of the full weeks between 2 dates, and also with the fraction of the remaining days before and after the 2 dates.
public static int getNumberOfFullWeeks(LocalDate startDate,LocalDate endDate)
{
int dayBeforeStartOfWeek = 0;
int daysAfterLastFullWeek = 0;
if(startDate.getDayOfWeek() != DayOfWeek.MONDAY)
{
// get the partial value before loop starting
dayBeforeStartOfWeek = 7-startDate.getDayOfWeek().getValue() + 1;
}
if(endDate.getDayOfWeek() != DayOfWeek.SUNDAY)
{
// get the partial value after loop ending
daysAfterLastFullWeek = endDate.getDayOfWeek().getValue();
}
LocalDate d1 = startDate.plusDays(dayBeforeStartOfWeek); // now it is the first day of week;
LocalDate d2 = endDate.minusDays(daysAfterLastFullWeek); // now it end in the last full week
// Count how many days there are of full weeks that start on Mon and end in Sun
// if the startDate and endDate are less than a full week the while loop
// will not iterate at all because d1 and d2 will be the same date
LocalDate looper = d1;
int counter = 1;
while (looper.isBefore(d2))
{
counter++;
looper = looper.plusDays(1);
}
// Counter / 7 will always be an integer that will represents full week
// because we started to count at Mon and stop counting in Sun
int fullWeeks = counter / 7;
System.out.println("Full weeks between dates: "
+ fullWeeks + " Days before the first monday: "
+ dayBeforeStartOfWeek + " "
+ " Days after the last sunday: " + daysAfterLastFullWeek);
System.out.println(startDate.toString() + " - " + endDate.toString());
// You can also get a decimal value of the full weeks plus the fraction if the days before
// and after the full weeks
float full_weeks_decimal = (float)fullWeeks;
float fraction = ((float)dayBeforeStartOfWeek + (float)daysAfterLastFullWeek) / 7.0F;
System.out.println("Full weeks with fraction: " + String.valueOf(fraction + full_weeks_decimal));
return fullWeeks;
}
public static int getNumberOfFullWeeks_WeekStartAtSunday(LocalDate startDate,LocalDate endDate)
{
int dayBeforeStartOfWeek = 0;
int daysAfterLastFullWeek = 0;
if(startDate.getDayOfWeek() != DayOfWeek.SUNDAY)
{
// get the partial value before loop starting
dayBeforeStartOfWeek = 7-getDayOfWeekBySundayIs0(startDate.getDayOfWeek()) + 1;
}
if(endDate.getDayOfWeek() != DayOfWeek.SATURDAY)
{
// get the partial value after loop ending
daysAfterLastFullWeek = 1+getDayOfWeekBySundayIs0(endDate.getDayOfWeek());
}
LocalDate d1 = startDate.plusDays(dayBeforeStartOfWeek); // now it is the first day of week;
LocalDate d2 = endDate.minusDays(daysAfterLastFullWeek); // now it end in the last full week
// Count how many days there are of full weeks that start on Sun and end in Sat
// if the startDate and endDate are less than a full week the while loop
// will not iterate at all because d1 and d2 will be the same date
LocalDate looper = d1;
int counter = 1;
while (looper.isBefore(d2))
{
counter++;
looper = looper.plusDays(1);
}
// Counter / 7 will always be an integer that will represents full week
// because we started to count at Sun and stop counting in Sat
int fullWeeks = counter / 7;
System.out.println("Full weeks between dates: "
+ fullWeeks + " Days before the first sunday: "
+ dayBeforeStartOfWeek + " "
+ " Days after the last saturday: " + daysAfterLastFullWeek);
System.out.println(startDate.toString() + " - " + endDate.toString());
// You can also get a decimal value of the full weeks plus the fraction if the days before
// and after the full weeks
float full_weeks_decimal = (float)fullWeeks;
float fraction = ((float)dayBeforeStartOfWeek + (float)daysAfterLastFullWeek) / 7.0F;
System.out.println("Full weeks with fraction: " + String.valueOf(fraction + full_weeks_decimal));
return fullWeeks;
}
public static int getDayOfWeekBySundayIs0(DayOfWeek day)
{
if(day == DayOfWeek.SUNDAY)
{
return 0;
}
else
{
// NOTE: getValue() is starting to count from 1 and not from 0
return day.getValue();
}
}
If you want exact number of full weeks use below method, where end date is exclusive:
public static long weeksBetween(Date date1, Date date2) {
return WEEKS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
}
If you want a ceil version of this, use below:
public static long weeksBetween(Date date1, Date date2) {
long daysBetween = DAYS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) + 1;
return daysBetween / 7 + (daysBetween % 7 == 0 ? 0 : 1);
}
You may do it the following way:
// method header not shown
// example dates:
f = new GregorianCalendar(2009,Calendar.AUGUST,1);
l = new GregorianCalendar(2010,Calendar.SEPTEMBER,1);
DateTime start = new DateTime(f);
DateTime end = new DateTime(l);
// Alternative to above - example dates with joda:
// DateTime start = new DateTime(2009,8,1,0,0,0,0);
// DateTime end = new DateTime(2010,9,1,0,0,0,0);
Interval interval = new Interval(start,end);
int weeksBetween = interval.toPeriod(PeriodType.weeks()).getWeeks();
// return weeksBetween;
This should give you an int representing the number of weeks between the two dates.
Joda Time computes weeks with durations of two dates which may not meet our requirements in some cases. I have a method with Joda Time to compute natural weeks between two dates. Hope it can help you. If you don't use Joda Time, you may modify the code with Calendar to do the same thing.
//Unlike Joda Time Weeks.weeksBetween() that returns whole weeks computed
//from duration, we return natural weeks between two dates based on week of year
public static int weeksBetween(ReadablePartial date1, ReadablePartial date2) {
int comp = date1.compareTo(date2);
if (comp == 0) {
return 0;
}
if (comp > 0) {
ReadablePartial mid = date2;
date2 = date1;
date1 = mid;
}
int year1 = date1.get(DateTimeFieldType.weekyear());
int year2 = date2.get(DateTimeFieldType.weekyear());
if (year1 == year2) {
return date2.get(DateTimeFieldType.weekOfWeekyear()) - date1.get(DateTimeFieldType.weekOfWeekyear());
}
int weeks1 = 0;
LocalDate lastDay1 = new LocalDate(date1.get(DateTimeFieldType.year()), 12, 31);
if (lastDay1.getWeekyear() > year1) {
lastDay1 = lastDay1.minusDays(7);
weeks1++;
}
weeks1 += lastDay1.getWeekOfWeekyear() - date1.get(DateTimeFieldType.weekOfWeekyear());
int midWeeks = 0;
for (int i = year1 + 1; i < year2; i++) {
LocalDate y1 = new LocalDate(i, 1, 1);
int yearY1 = y1.getWeekyear();
if (yearY1 < i) {
y1 = y1.plusDays(7);
midWeeks++;
}
LocalDate y2 = new LocalDate(i, 12, 31);
int yearY2 = y2.getWeekyear();
if (yearY2 > i) {
y2 = y2.minusDays(7);
midWeeks++;
}
midWeeks += y2.getWeekOfWeekyear() - y1.getWeekOfWeekyear();
}
int weeks2 = 0;
LocalDate firstDay2 = new LocalDate(date2.get(DateTimeFieldType.year()), 1, 1);
if (firstDay2.getWeekyear() < firstDay2.getYear()) {
firstDay2 = firstDay2.plusDays(7);
weeks2++;
}
weeks2 += date2.get(DateTimeFieldType.weekOfWeekyear()) - firstDay2.getWeekOfWeekyear();
return weeks1 + midWeeks + weeks2;
}
int startWeek = c1.get(Calendar.WEEK_OF_YEAR);
int endWeek = c2.get(Calendar.WEEK_OF_YEAR);
int diff = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
int deltaYears = 0;
for(int i = 0;i < diff;i++){
deltaYears += c1.getWeeksInWeekYear();
c1.add(Calendar.YEAR, 1);
}
diff = (endWeek + deltaYears) - startWeek;
Includes the year differences.
This worked for me :)
private int weeksBetween(Calendar startDate, Calendar endDate) {
startDate.set(Calendar.HOUR_OF_DAY, 0);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
int start = (int)TimeUnit.MILLISECONDS.toDays(
startDate.getTimeInMillis())
- startDate.get(Calendar.DAY_OF_WEEK);
int end = (int)TimeUnit.MILLISECONDS.toDays(
endDate.getTimeInMillis());
return (end - start) / 7;
}
if this method returns 0 they are in the same week
if this method return 1 endDate is the week after startDate
if this method returns -1 endDate is the week before startDate
you get the idea
Without using JodaTime, I was able to accurately calculate the number of weeks between 2 calendars (which accounts for leap years etc.)
private fun calculateNumberOfWeeks() {
val calendarFrom = Calendar.getInstance()
calendarFrom.set(Calendar.HOUR_OF_DAY, 0)
calendarFrom.set(Calendar.MINUTE, 0)
calendarFrom.set(Calendar.SECOND, 0)
calendarFrom.set(Calendar.MILLISECOND, 0)
val calendarTo = Calendar.getInstance()
calendarTo.add(Calendar.MONTH, months)
calendarTo.set(Calendar.HOUR_OF_DAY, 0)
calendarTo.set(Calendar.MINUTE, 0)
calendarTo.set(Calendar.SECOND, 0)
calendarTo.set(Calendar.MILLISECOND, 0)
var weeks = -1
while (calendarFrom.timeInMillis < calendarTo.timeInMillis) {
calendarFrom.add(Calendar.DATE, 7)
weeks++
Log.d(Constants.LOG_TAG, "weeks $weeks")
}
}
Easy way
Calendar cal1 = new GregorianCalendar();
Calendar cal2 = new GregorianCalendar();
cal1.set(2014, 3, 3);
cal2.set(2015, 3, 6);
weekscount.setText("weeks= "+ ( (cal2.getTime().getTime() - cal1.getTime().getTime()) / (1000 * 60 * 60 * 24))/7);
Here is a simple way to find the number of weeks between two dates.
SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String classStartData = "31 01 2021";
String classEndData = "08 03 2021";
Date dateClassStart = myFormat.parse(classStartData);
Date dateClassEnd = myFormat.parse(classEndData);
long differenceWeek = dateClassEnd.getTime() - dateClassStart.getTime();
int programLength = (int)(TimeUnit.DAYS.convert(differenceWeek, TimeUnit.MILLISECONDS)/7);
System.out.println("Class length in weeks: " +programLength);
After referring many solution, this worked for me.
{Provided I did not want to use external Libraries}
public static int getNumberOfWeeks(Date date1, Date date2) {
if (date1.after(date2)) {
return getNumberOfWeeks(date2, date1);
}
Date date = date1;
int days = 0;
while (date.before(date2)) {
days++;
date = addDays(date, 1);
}
return days/7;
}
To add days to a date :
Date addDays(Date date, int days) {
if (days == 0) {
return date;
} else {
Date shiftedDate = new Date(date.getTime() + (long)days * 86400000L);
return shiftedDate;
}
}
Take a look at the following article: Java - calculate the difference between two dates
The daysBetween method will allow you to get the number of days between dates. Then you can simply divide by 7 to get the number of full weeks.
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
date1.clear();
date1.set(datePicker1.getYear(), datePicker1.getMonth(),
datePicker1.getDayOfMonth());
date2.clear();
date2.set(datePicker2.getYear(), datePicker2.getMonth(),
datePicker2.getDayOfMonth());
long diff = date2.getTimeInMillis() - date1.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
int week = (dayCount / 7) ;
Hope this might Help you
public int diffInWeeks(Date start, Date end) {
long diffSeconds = (end.getTime() - start.getTime())/1000;
return (int)diffSeconds/(60 * 60 * 24 * 7);
}

Categories