Get time difference in years in android - java

Hello I'm able to get the seconds, minutes, hours and days, but when I try to get the years the problem comes up.
I'm using the following code:
Calendar startDate = new GregorianCalendar(year, month, day);
Calendar date = Calendar.getInstance();
long diff = date.getTimeInMillis() - startDate.getTimeInMillis();
long seconds = diff / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
long days = hours / 24;
double years = date.get(Calendar.YEAR) - startDate.get(Calendar.YEAR);
Let's say the start date is 07/25/1994 and the end date is 07/28/2015
the result that I get is (21.0) instead of the of 20.97 . I need to get the exact age in YEARS for the users so; can you help me guys out?. Thanks!

Use BigDecimal instead of double and long. When you want precise calculations of floating point numbers, always use BigDecimal. Floating point math is not reliable in java. Simple example is System.out.println(2.00 - 1.10); guess what, it doesnt print .90.

You need to cast your variables:
double years = (double) date.get(Calendar.YEAR) - (double) startDate.get(Calendar.YEAR);

Is your question about elapsed time or about decimal number calculation?
If the first, you should know that decimal numbers for elapsed years is somewhat odd. If the second, you should change the title of your Question.
Elapsed Time
For Android, you should be using the Joda-Time library rather than the old java.util.Date/.Calendar classes. The old classes are notoriously troublesome.
The ISO 8601 standard defines string formats for various kinds of date-time values. For a span of time in terms of a count of years, months, days, hours, minutes, and seconds, the format is PnYnMnDTnHnMnS where P defines the beginning and T separates the days portion from hours portion. The Question is about a span of P21Y3D, or 21 years and 3 days. The Joda-Time library uses this standard format for both parsing and generating such strings.
LocalDate start = new LocalDate( 1994, 7, 25 ); // 07/25/1994
LocalDate stop = new LocalDate( 2015, 7, 28 ); // 07/28/2015
Period period = new Period( start, stop );
System.out.println("start: " + start + " to stop: " + stop + " is " + period );
When run.
start: 1994-07-25 to stop: 2015-07-28 is P21Y3D
Decimal Number Calculation
If you are just asking about the decimal numbers, then the answer by Samrat Dutta is correct: Use BigDecimal if you care about accuracy. Otherwise you are using primitives with floating-point calculations. Floating-point trades off accuracy for speed of execution. As a general rule, if in doubt about which to use for business problems, go with BigDecimal rather than floating-point.
What do you mean by "exact age in years"? Here's the number of years with up to 200 decimal places:
21.00752908966461327857631759069130732375085557837097878165639972621492128678986995208761122518822724161533196440793976728268309377138945927446954140999315537303216974674880219028062970568104038329911020
Integer days = Days.daysBetween( start, stop ).getDays( );
BigDecimal daysPerYear = new BigDecimal( 365.25 ); // Approximate.
int scale = 200; // Number of fractional digits desired.
BigDecimal years = new BigDecimal( days ).divide( daysPerYear, scale, RoundingMode.HALF_EVEN ); // Banker's rounding.
System.out.println( "days: " + days + " ÷ " + daysPerYear + " = " + years + " years." );
When run.
days: 7673 ÷ 365.25 = 21.00752908966461327857631759069130732375085557837097878165639972621492128678986995208761122518822724161533196440793976728268309377138945927446954140999315537303216974674880219028062970568104038329911020 years.
As I said, you may find P21Y3D makes more sense than this decimal number.

Related

Dividing seconds by 60 twice to get hours results in zero

I'm trying to convert the number of seconds contained in a duration into hours by dividing the duration.getSeconds() value by 60 twice.
However when I do this the number is being converted into 0.0, instead of an actual value. I imagine this is because the number is too small to be represented, however I have used doubles to try and represent the number and it still doesn't work.
In the below code please assume startTime and endTime are valid LocalTimes produced by two separate calls to LocalTime.now()
Duration duration = Duration.between(startTime, endTime); //duration in sec
double durationInSec = duration.getSeconds();
double durationInHours = durationInSec / 60 / 60;
Works for me
LocalTime start = LocalTime.of ( 11 , 30 );
LocalTime stop = start.plusHours ( 2 );
Duration d = Duration.between ( start , stop );
double seconds = d.toSeconds ();
double hours = seconds / 60 / 60;
See this code run live at IdeOne.com.
start.toString() = 11:30
stop.toString() = 13:30
d.toString() = PT2H
seconds = 7200.0
hours = 2.0
Tip: When you know you want to work with fractions of double, append d to your numeric literals to avoid any confusion over the compiler's integer-to-fraction conversion and up/downscaling the types. Be explicit. So in your code, append each 60 with a d. May not be necessary here, but removes ambiguity for the reader at least.
double hours = seconds / 60d / 60d ;
<1 second = 0 hours
As others commented, if your elapsed time was less than a full second, your code results in a zero.
A Duration is internally represented by a count of whole seconds plus a fractional second as a count of nanoseconds. Your call to Duration::getSeconds() retrieves the whole seconds, without the fractional second. So for a duration of PT0.5S, getSeconds returns zero. Zero divided by sixty divided by sixty equals zero.
Duration d = Duration.parse ( "PT0.5S" ); // Half a second.
double hours = d.getSeconds () / 60d / 60d;
hours: 0.0
You should instead call Duration::toNanos to get a total number of nanoseconds elapsed. And adjust your division.
Duration d = Duration.parse ( "PT0.5S" ); // Half a second.
long nanos = d.toNanos () ;
double hours = nanos / 1_000_000_000d / 60d / 60d ;
hours: 1.388888888888889E-4
Avoid fractional hours
By the way, let me suggest that fractional hours is a poor way to handle spans-of-time. Hours, minutes, seconds, and such are not amenable to such decimal math.
Besides that, the floating-point types such as double are inherently inaccurate.
Use the Java classes intended for this purpose: Duration and Period. When reporting or exchanging textually the value of these objects, use standard ISO 8601 format. As seen above, 2 hours is represented by PT2H.
The java.time classes use ISO 8601 formats by default when parsing/generating strings. No need to specify a formatting pattern.
Duration d = Duration.parse( "PT2H" ) ;

How to calculate the number of days in a period?

For the following Period calculation:
Period.between(LocalDate.of(2015, 8, 1), LocalDate.of(2015, 9, 2))
the result is:
P1M1D
This is equivalent to 31 days + 1 day = 32 days.
For this Period:
Period.between(LocalDate.of(2015, 8, 1), LocalDate.of(2015, 10, 2))
the result is:
P2M1D
This is equivalent to: 31 days (in August) + 30 days (in September) + 1 (in October) = 62 days
Is there a method in the java.time package which will give the number of days in a Period? I can't find one. Not sure if I have overlooked anything or if it is just plain not there.
From the documentation:
To define an amount of time with date-based values (years, months,
days), use the Period class. The Period class provides various get
methods, such as getMonths, getDays, and getYears.To present the amount >of time measured in a single unit of time, such as days, you can use the
ChronoUnit.between method.
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1960, Month.JANUARY, 1);
Period p = Period.between(birthday, today);
long p2 = ChronoUnit.DAYS.between(birthday, today);
System.out.println("You are " + p.getYears() + " years, " + p.getMonths() +
" months, and " + p.getDays() +
" days old. (" + p2 + " days total)");
The code produces output similar to the following:
You are 53 years, 4 months, and 29 days old. (19508 days total)
There is no way to do what you ask. The reason is that it is not possible from a Period to deduce the actual number of calendar days in the period. A Period is not tied to specific dates, once constructed in the way you show, it loses track of the actual calendar dates.
For example your first period represents a period of 1 month and 1 day. But the period does not care which month. It is simply a concept of "a month and a day".
If you need the number of days between two dates you should use ChronoUnit.DAYS.between as Saket Mittal writes.
There's a specific object depending at the amount of time you'd like to deal with.
This page here is very useful explaining which is best for your scenario.
The ChronoUnit.between method is useful when you want to measure an amount of time in a single unit of time only, such as days or seconds
LocalDate localDateStartDate = LocalDate.of(2016, 06, 10);
LocalDate localDateEndDate = LocalDate.of(2016,06,23);
long days = ChronoUnit.DAYS.between(localDateStartDate, localDateEndDate);

how to find the total number of months between the two dates including extra days?

I have a requirement where I need to find out number of months between two dates including extra days.
example:
start date:01/01/2014
end date:21/02/2014
LocalDate startDate = new LocalDate(startDate1);
LocalDate endDate = new LocalDate(endDate1);
PeriodType monthDay =PeriodType.yearMonthDay().withYearsRemoved();
Period difference = new Period(startDate, endDate, monthDay);
int months = difference.getMonths();
int days = difference.getDays()
the out put I will get is:
months:1 days:20
but my requirement is I want get total months including that extra day.
like:1.66 months.
How to get this one in java?
In order to be able to say 1.66 months you need to define how long a month is. It's not always the same. If you assume that a month is 30 days long then you can solve this by using:
Date startDate = new SimpleDateFormat("dd/MM/yyyy").parse("01/01/2014");
Date endDate = new SimpleDateFormat("dd/MM/yyyy").parse("21/02/2014");
double result = (endDate.getTime() - startDate.getTime()) / (1000D*60*60*24*30);
This gives us 1.7 and if you divide with 31 you get 1.6451612903225807.
If you want a better (but not perfect) approximation of how long a month is you can try 365/12 which will give you 1.6767123287671233 but still this is not perfect because leap years have 366 days.
The problem though is not with the formula, but with the problem definition. Nobody in real life says "I'll be there in exactly 1.66 months" and nobody will ever ask you to convert 1.66 months in days.
This is my own answer, a variation on cherouvim's
final Date startDate = new GregorianCalendar (2014, 0, 1).getTime ();
final Date endDate = new GregorianCalendar (2014, 1, 21).getTime ();
System.out.println ((endDate.getTime () - startDate.getTime ()) / (float) (1000L * 60 * 60 * 24 * 30));

Represent date from long, starting from year 0 instead of 1970 [duplicate]

This question already has an answer here:
How to calculate difference between two dates in years...etc with Joda-Time
(1 answer)
Closed 8 years ago.
I have a long-variable which represents an amount of delay in milliseconds. I want to transform this long to some kind of Date where it says how many hours, minutes, seconds, days, months, years have passed.
When using Date toString() from Java, as in new Date(5).toString, it says 5 milliseconds have passed from 1970. I need it to say 5 milliseconds have passed, and 0 minutes, hours, ..., years.
you cannot get direct values , without any reference date for your requirements, you need define first reference value like below:
String dateStart = "01/14/2012 09:29:58";
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss")
Date d1 = format.parse(dateStart);
the above is your reference date , now you need to find the current date and time using following.
long currentDateTime = System.currentTimeMillis();
Date currentDate = new Date(currentDateTime);
Date d2.format(currentDate)
and the difference of these values like long diff=d2-d1 will gives values in milliseconds.
then
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);
and similarly for months and years.
you can also refer the example given on this link for more information http://javarevisited.blogspot.in/2012/12/how-to-convert-millisecond-to-date-in-java-example.html
From what I understand from your question you could achieve your goal by writing a method that will suit your needs i.e.:
static public String dateFromMili (long miliseconds) {
// constants that will hold the number of miliseconds
// in a given time unit (year, month etc.)
final int YEAR_IN_MILISECONDS = 12*30*24*60*60*1000;
final int MONTH_IN_MILISECONDS = 30*24*60*60*1000;
final int DAY_IN_MILISECONDS = 24*60*60*1000;
final int HOUR_IN_MILISECONDS = 60*60*1000;
final int MINUTE_IN_MILISECONDS = 60*1000;
final int SECONDS_IN_MILISECONDS = 1000;
// now use those constants to return an appropriate string.
return miliseconds +" miliseconds, "
+miliseconds/SECONDS_IN_MILISECONDS+" seconds, "
+miliseconds/MINUTE_IN_MILISECONDS+" minutes, "
+miliseconds/HOUR_IN_MILISECONDS+" hours, "
+miliseconds/DAY_IN_MILISECONDS+" days, "
+miliseconds/MONTH_IN_MILISECONDS+" months, "
+miliseconds/YEAR_IN_MILISECONDS+" years have passed";
}
Than you will have to pas the number of miliseconds as a parameter to your new function that will return the desired String (i.e for two seconds):
dateFromMili (2000);
You could also print your answer:
System.out.println(dateFromMili(2000));
The result would look like this:
2000 miliseconds, 2 seconds, 0 minutes, 0 hours, 0 days, 0 months, 0 years have passed
Note that this method will return Strings with integer value (you will not get for example "2.222333 years" but "2 years"). Furthermore, it could be perfected by changing the noun from plural to singular, when the context is appropriate ("months" to "month").
I hope my answer helped.
This is how I solved the problem:
I used a library called Joda-Time (http://www.joda.org/joda-time/) (credits to Keppil!)
Joda-Time has various data-structures for Date and Time. You can represent a date and time by a DateTime-object.
To represent the delay I was looking for, I had two options: a Period data-structure or a Duration data-structure. A good explanation of the difference between those two can be found here: Joda-Time: what's the difference between Period, Interval and Duration? .
I thus used a Duration-object, based on the current date of my DateTime-object. It has all the methods to convert the amount of milliseconds to years, months, weeks, days, hours, minutes and seconds.

Returning time in minutes [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I am trying to find difference between 2 times in minutes with following code.not providing complete code:
String dateStart = "03/25/2014 18:03:00";
String dateStop = "03/25/2014 19:45:00";
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date d1 = null;
Date d2 = null;
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
long diff = endDate.getTime()-startDate.getTime();
long minutes = diff/(60*1000) % 60;
not sure why it is returnung 14 minutes. instead 102 minutes.
Regards,
chaitu
Joda-Time
In Joda-Time, use the Minutes class. Basically one line of code, calling minutesBetween.
Example Code
Here is some example code in Joda-Time 2.3.
Parsing those strings
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MM/dd/yyyy HH:mm:ss" ).withZone( timeZone );
DateTime start = formatter.parseDateTime( "03/25/2014 18:03:00" );
DateTime stop = formatter.parseDateTime( "03/25/2014 19:45:00" );
Calculating minutes between
int minutes = Minutes.minutesBetween( start, stop ).getMinutes();
ISO Duration (Period)
Or you may want to generate a string in the ISO 8601 format of Durations: PnYnMnDTnHnMnS. To do so in Joda-Time, use the Period class (yes, date-time terminology is not standardized, used differently by different folks).
Period period = new Period( start, stop );
String output = period.toString();
Results
Dump to console…
System.out.println( "start: " + start );
System.out.println( "stop: " + stop );
System.out.println( "minutes: " + minutes );
System.out.println( "period: " + period );
When run…
start: 2014-03-25T18:03:00.000+01:00
stop: 2014-03-25T19:45:00.000+01:00
minutes: 102
period: PT1H42M
That output of PT1H42M means "one hour and forty-two minutes".
Time Zone
Your question and code ignored the crucial issue of time zone in parsing those strings. You should almost always specify a time zone.
java.time
The new java.time package in Java 8 may have similar features as what you’ve seen here with Joda-Time.
long diff = endDate.getTime()-startDate.getTime();
makes diff the difference between the two times in milliseconds (6120000). To get seconds, divide by 1000 (6120). To get minutes, divide the result of that by 60 (102).
To get utter nonsense, further take mod 60 (gives 42).
(Note that this is a mathematical error, not really a question about Java.)
To get the difference in minutes, you have can use:
long minutes = diff / (60 * 1000);
When you do:
long minutes = diff / (60 * 1000) % 60;
you are getting the difference of minutes between the dates. In other words, you are only considering minutes; not hours, nor days...
The modulus operation in your code isn't needed. Remember that the modulus operator gives you the remainder of an operation. If you take out the "% 60;" part of your code, it should work.
Fixed calculation:
long minutes = diff/(60*1000);
The situation where you'd want to use the modulus operator is if you wanted to express the difference also in units that are greater than a minute, such as hours or days. In this case you'd use the modulus operator to make sure you'd only extract the number of minutes that are less than 60.

Categories

Resources