1

I know that taking a different route to calculate the age is explained here already: Calculate age from BirthDate

But I'm interested in knowing why my method isn't working. I'm getting today's date in milliseconds, getting the birthday the user picked in milliseconds, and so calculating the year's difference to get the age, but it's inaccurate:

       todayCalender  = Calendar.getInstance()

        val mCustomDatePicker = layoutInflater.inflate(com.example.meet.R.layout.custom_date_picker, activityStageOne, false)

        val mDatePicker = mCustomDatePicker.findViewById(com.example.meet.R.id.mDatePicker) as DatePicker
        mDatePicker.maxDate = (Calendar.getInstance().getTime().getTime())
        val mDialog = AlertDialog.Builder(this)
        mDialog.setView(mCustomDatePicker)

        addListenersForEditText()

        mDialog.setPositiveButton("OK", object : DialogInterface.OnClickListener {
            override fun onClick( dialog: DialogInterface, which: Int) {

                val mCalendar  = Calendar.getInstance()
                mCalendar.set(mDatePicker.year, mDatePicker.month, mDatePicker.dayOfMonth)

                var difference = todayCalender!!.timeInMillis - mCalendar.timeInMillis
                var floating = difference.toFloat()

                Log.d("TAG", (((floating/1000/360/24/60/60))).toString())

                ageET.setText((mDatePicker.month + 1).toString() + " / " + mDatePicker.dayOfMonth.toString() + " / " + mDatePicker.year.toString())
            }

The actual calculation:

            var difference = todayCalender!!.timeInMillis - mCalendar.timeInMillis
            var floating = difference.toFloat()

            Log.d("TAG", (((floating/1000/360/24/60/60))).toString())

When I select the date as January 6th (today's day and month) with the year 2000, I expect "20" to be logged (or very close to 20), but instead, it logs 20.29

Using floor is not a solution since the inaccuracy grows as you go back in the years and the error could be larger than one year

What makes it inaccurate?

sandpat
  • 1,478
  • 12
  • 30
sir-haver
  • 3,096
  • 7
  • 41
  • 85

2 Answers2

3

Just to show how short and clear such a calculation may become using java.time compared to the code you already have (assuming a working version):

fun main() {
    // get the date of birth (maybe from a DatePicker)
    var birthday = java.time.LocalDate.of(2000, 1, 6)
    // calculate the current age (in years only)
    val age = java.time.Period.between(birthday, java.time.LocalDate.now()).getYears()
    // print the result
    println(age)
}

This simply prints 20.

Since you are using a DatePicker and a reference to the current day, you don't have to go the way calculating anything based on milliseconds.

Consider using modern APIs, Date and Calendar are outdated and their use should be avoided.

But you are supporting lower API levels than 26, which causes the need of importing a certain library (its use in Java is explained here) in order to use java.time. That's the (only) downside of this...

deHaar
  • 17,687
  • 10
  • 38
  • 51
  • Thank you very much! Yes now I realize all the cons of using milliseconds, obviously that's not the way to go, and I'll check out the library you suggested so I can use the code in your answer for lower APIs – sir-haver Jan 06 '20 at 07:33
  • 2
    I would just like to add that if you do use the library you have to omit the "java.time" – sir-haver Jan 06 '20 at 08:40
  • True, @sir-haver. If you are using [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP), `LocalDate` and `Period` (and the other “java.time” classes) are in the `org.threeten.bp` package instead. – Ole V.V. Jan 08 '20 at 03:20
2

Because a Leap Year have 366 days. And a common year is 365 days. I think you use the 360 days.

littlebear333
  • 710
  • 2
  • 6
  • 14
  • You're right but it still doesn't explain that large error, I did find that you have to divide by 31536000, and then the error is very small and is due to leap years thanks for your help anyhow! – sir-haver Jan 06 '20 at 07:15
  • I find that the other problem is the float result. Floats are binary fractions internally. So the result is not accurate. I think you should use BigDecimal to calculate it again. – littlebear333 Jan 06 '20 at 07:51
  • 365.25 / 360 = 1.01458. 20.29 / 20 = 1.0145. I think that this answer is to the point regarding the inaccuracy in your calculation. – Ole V.V. Jan 08 '20 at 03:17