androidkotlinandroid-datepickerandroid-date

Calculate age from birthday in milliseconds


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?


Solution

  • 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...