Home > Mobile >  Index out bounds exception when storing time in milliseconds [Android]
Index out bounds exception when storing time in milliseconds [Android]

Time:08-19

I am storing time in Milliseconds using a Material Time Picker Dialog. The problem is if I choose a time instance which is like a single valued hour (between 1-9) or single valued minute(1-9) then I am able to get the value in milliseconds. But if I set the bigger values of time I get an exception java.lang.ArrayIndexOutOfBoundsException: length=17; index=20

What am I doing wrong here? Or what is the better approach to do this.

Log for reference :

Image

My Code (Not the complete code but what is required for this question) :

 //Time Picker
    var picker: MaterialTimePicker = MaterialTimePicker()

    //Long values to be stored in database
    val timeStart: Long = 0


 //Setting Start Time
        binding.timeStart.setOnClickListener {
            openTimePicker()
            picker.addOnPositiveButtonClickListener {
                val h = picker.hour
                val m = picker.minute
                binding.timeStart.text = "$h:$m"
                Timber.d("Start Time - h: $h m: $m")
                try {
                    val calendar = Calendar.getInstance()
                    calendar.get(h)
                    calendar.get(m)
                    val timeInMilliSeconds = calendar.timeInMillis
                    Timber.d("$timeInMilliSeconds")
                } catch (e: Exception) {
                    Timber.d("$e")
                }
            }
        }

 private fun openTimePicker() {
        val isSystem24Hour = is24HourFormat(requireContext())
        val clockFormat = if (isSystem24Hour) TimeFormat.CLOCK_24H else TimeFormat.CLOCK_12H

        picker = MaterialTimePicker.Builder()
            .setTimeFormat(clockFormat)
            .setHour(12)
            .setMinute(10)
            .setTitleText("Set Start Time")
            .build()
        picker.show(childFragmentManager, "TAG")
    }

CodePudding user response:

It's happening here:

val h = picker.hour
val m = picker.minute
binding.timeStart.text = "$h:$m"
Timber.d("Start Time - h: $h m: $m")
try {
    val calendar = Calendar.getInstance()
    calendar.get(h)
    calendar.get(m)
    val timeInMilliSeconds = calendar.timeInMillis
    Timber.d("$timeInMilliSeconds")
}

Specifically when you call calendar.get()

public int get (int field)

Returns the value of the given calendar field Throws ArrayIndexOutOfBoundsException if the specified field is out of range (field < 0 || field >= FIELD_COUNT)

public static final int FIELD_COUNT

The number of distinct fields recognized by get and set. Field numbers range from 0..FIELD_COUNT-1

Constant Value: 17

That's why your exception is complaining that the array has 17 items and you're trying to access index 20, because you're passing values representing hours and minutes instead of field constants.

I'm not sure what you want to do exactly, but look at the set or add methods in the Calendar class, if you want to specify an exact time or you want to add x hours and y minutes to the current time. You'll need to use the field constants to specify which value you're changing, e.g. HOUR_OF_DAY

CodePudding user response:

A better approach to get the time in milliseconds using TimeUnit instead of Calendar. I used TimeUnit.HOURS.toMillis(myHours) and TimeUnit.MINUTES.toMillis(myMinutes) to get my hours and minutes in milliseconds and then add them to get the time in milliseconds.

Code :

binding.timeStart.setOnClickListener {
            openTimePicker()
            picker.addOnPositiveButtonClickListener {
                val h = picker.hour
                val m = picker.minute
                binding.timeStart.text = "$h:$m"
                Timber.d("Start Time - $h: $m")
                try {
                    val hour = TimeUnit.HOURS.toMillis(h.toLong())
                    val minute = TimeUnit.MINUTES.toMillis(m.toLong())
                    val totalTime = hour   minute

                    Timber.d("Hour - $hour, Minute - $minute, Total = $totalTime")
                    timeStart = totalTime

                } catch (e: Exception) {
                    Timber.d("$e")
                }
            }
        }

    private fun openTimePicker() {
        picker = MaterialTimePicker.Builder()
            .setTimeFormat(TimeFormat.CLOCK_12H)
            .setHour(12)
            .setMinute(10)
            .setTitleText("Set Start Time")
            .build()
        picker.show(childFragmentManager, "TAG")
    }
  • Related