Very weird. I know. This is the executing code.
(Code in the EDIT.)
Once I select a time and a date, and do the same again, the previous output text differs from this output text.
Note that the user setting is 24 hour format.
First time doing it:
Here's how it looks after doing the first time (ignore the highlighted "person", that is an implementation of a search mechanism for contacts):
THEN, the same thing again (I swear this is the second time I'm doing this, it might look the same):
But what is this monstrosity?!
Toasts confirm that both the time I'm entering the 24 hour if-clause, so I think that choosing the right format for date is fine. (Also note that if it were 12 hour format, an AM/PM would have been there as suggested by the code but isn't there in the output).
I don't know how this could be happening. The SimpleDateFormat
is instantiated right before usage, so messing with it anywhere else is not possible, so I don't think it's coming from datePickerDialog
.
Any clues/suggestions/ideas?
EDIT: As requested, here's the Adapter code. I'm new so please go easy on me :)
The relevant code is in fun setDateTime()
class ContactAdapter(
private val context: Context,
private val contact_name: String?,
private val items: List<Contact>
) :
RecyclerView.Adapter<ContactAdapter.ViewHolder>() {
private val c = Calendar.getInstance()
fun createDatePicker(onSetDate: (DatePicker, Int, Int, Int) -> Unit) = DatePickerDialog(
context,
onSetDate,
c[Calendar.YEAR],
c[Calendar.MONTH],
c[Calendar.DAY_OF_MONTH]
)
fun createTimePicker(onSetTime: (TimePicker, Int, Int) -> Unit) = TimePickerDialog(
context,
onSetTime,
c[Calendar.HOUR],
c[Calendar.MINUTE],
DateFormat.is24HourFormat(context)
)
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
setupAddButton()
setupGreetingTimeText()
}
private fun setDateTime() {
val datePicker = createDatePicker { _, year, month, date ->
c[Calendar.YEAR] = year
c[Calendar.MONTH] = month
c[Calendar.DAY_OF_MONTH] = date
val timePicker = createTimePicker { _, hour, minute ->
c[Calendar.HOUR] = hour
c[Calendar.MINUTE] = minute
itemView.txtGreetingTime.text = if (DateFormat.is24HourFormat(context)) {
Toast.makeText(context, "Chose 24-hour clause", Toast.LENGTH_SHORT).show()
SimpleDateFormat(
"dd mmm, yyyy 'at' HH:mm",
Locale.getDefault()
).format(c.time)
} else {
Toast.makeText(context, "Chose 12-hour clause", Toast.LENGTH_SHORT).show()
SimpleDateFormat(
"dd mmm, yyyy 'at' hh:mm aa",
Locale.getDefault()
).format(c.time)
}
}
// Do time picking stuff
timePicker.show()
}
// Do date picking stuff
datePicker.show()
}
private fun setupAddButton() {
itemView.addButton.setOnClickListener {
println("Attempted call to ${itemView.contactPhone.text}")
itemView.layoutTimingDetails.visibility =
if (itemView.layoutTimingDetails.visibility == View.VISIBLE) View.GONE else View.VISIBLE
}
}
private fun setupGreetingTimeText() {
itemView.txtGreetingTime.setOnClickListener {
it.txtGreetingTime.text = dateTimeToString()
}
}
fun setData(item: Contact, contact_name: String?) {
itemView.contactName.text = item.name
itemView.contactPhone.text = item.phone
itemView.contactEmail.text = item.email
if (contact_name != null)
itemView.contactName.highlightBackground(contact_name, Color.YELLOW)
}
}
override fun getItemCount(): Int = items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.card_contact, parent, false)
)
override fun onBindViewHolder(holder: ViewHolder, position: Int) =
holder.setData(items[position], contact_name)
}
EDIT 2: Earlier I thought that SimpleDateFormat was at fault here. But it is actually the TimePicker. It's somehow wrongly interpreting a click on 24 hour buttons and instead registering their counterpart 12 hour buttons as input.
Example if I chose 18:30 as the time the first time, then if I chose 6:30 as the time the second time, the time generated is still 18:30. However, if for the third time is changed to 18:30, now the registered time is 6:30.
I created a DateTimePickerSample
to help you. Original issue was wrong use of HOUR
from java.util.Calendar
. Using HOUR_OF_DAY
returns correct results.
From Java Documenation
HOUR
: Field number for get and set indicating the hour of the morning or afternoon.HOUR_OF_DAY
: Field number for get and set indicating the hour of the day.
Usage:
val picker = DateTimePickerSample(this)
picker.pickDateTime(
usePreviousCalendar = true,
callback = object: DateTimePickerSample.Callback {
override fun onDateTimeSetSet(dateTimeStr: String, is24HourFormat: Boolean) {
Log.d("Duh", "date=$dateTimeStr, is24HourFormat=$is24HourFormat")
}
}
)
DateTimePickerSample.kt
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.Context
import android.text.format.DateFormat
import android.widget.DatePicker
import android.widget.TimePicker
import java.text.SimpleDateFormat
import java.util.*
class DateTimePickerSample(
private val context: Context
) : DatePickerDialog.OnDateSetListener,
TimePickerDialog.OnTimeSetListener {
interface Callback {
fun onDateTimeSetSet(dateTimeStr: String, is24HourFormat: Boolean)
}
private var callback: Callback? = null
private var calendar = Calendar.getInstance()
private val is24HourFormat = DateFormat.is24HourFormat(context)
fun pickDateTime(usePreviousCalendar: Boolean, callback: Callback) {
this.callback = callback
if (!usePreviousCalendar) {
this.calendar = Calendar.getInstance()
}
val datePickerDialog = createDatePicker()
datePickerDialog.show()
}
private fun createDatePicker(): DatePickerDialog {
return DatePickerDialog(
context,
this,
calendar[Calendar.YEAR],
calendar[Calendar.MONTH],
calendar[Calendar.DAY_OF_MONTH]
)
}
private fun createTimePicker(): TimePickerDialog {
return TimePickerDialog(
context,
this,
calendar[Calendar.HOUR_OF_DAY],
calendar[Calendar.MINUTE],
is24HourFormat
)
}
/*
* DatePickerDialog.OnDateSetListener
*/
override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
calendar[Calendar.YEAR] = year
calendar[Calendar.MONTH] = month
calendar[Calendar.DAY_OF_MONTH] = dayOfMonth
val timePickerDialog = createTimePicker()
timePickerDialog.show()
}
/*
* TimePickerDialog.OnTimeSetListener
*/
override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) {
calendar[Calendar.HOUR_OF_DAY] = hourOfDay
calendar[Calendar.MINUTE] = minute
val dateFormatter = if (is24HourFormat) {
SimpleDateFormat("dd mmm, yyyy 'at' HH:mm", Locale.getDefault())
} else {
SimpleDateFormat("dd mmm, yyyy 'at' hh:mm aa", Locale.getDefault())
}
val dateTimeStr = dateFormatter.format(calendar.time)
callback?.onDateTimeSetSet(dateTimeStr, is24HourFormat)
}
}