为何安卓TimePickerDialog选择PM后仍自动设置为AM?
核心问题
你的bug根源是手动换算时间的过程里把上下午(AM/PM)的标记信息给丢了,错把24小时制的时间值做了无效截断,导致Calendar根本识别不到你选的是PM时段。
具体错处拆解:
- TimePickerDialog回调的
hourOfDay是0-23范围的24小时制数值,比如下午2点会返回14 - 你拿到值后写了个逻辑:只要小时大于12就减12,把14算成2,之后直接把这个2塞给
Calendar.HOUR_OF_DAY字段 - 这个字段本来就是用来存0-23范围的24小时值的,当你传入2的时候,Calendar默认把它当成凌晨2点(AM),原来PM的时段信息在你减12的那步就已经全丢了,最后格式化出来的结果自然永远是AM。
实际复现场景:你选下午3点(PM),回调返回hourOfDay=15
- 原代码算出来hr=15-12=3
- 给Calendar的HOUR_OF_DAY赋值3,Calendar自动判定这是凌晨3点
- 格式化输出的就是
3:00 AM,和你选PM的预期完全反过来
正确实现
根本不用自己手动做24小时制转12小时制的计算,Calendar本身就能根据传入的0-23范围的小时值,自动匹配对应的上下午标记:
- 直接把回调返回的原始
hourOfDay值传给Calendar.HOUR_OF_DAY字段 - 保留原来的
SimpleDateFormat("h:mm a")格式化规则就行,它会根据Calendar存的时间值自动输出对应的AM/PM标记
修正后可直接用的代码
private fun timePicker() { val cal = Calendar.getInstance() val timelistener = TimePickerDialog.OnTimeSetListener { _, hourOfDay, minute -> // 删掉多余的手动减12的换算逻辑,直接用原始值赋值 cal.set(Calendar.HOUR_OF_DAY, hourOfDay) cal.set(Calendar.MINUTE, minute) binding.addMoretimeStamp.text = SimpleDateFormat("h:mm a").format(cal.time) } TimePickerDialog( requireContext(), timelistener, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), false ).show() }
补充提示
如果之后你一定要用12小时制的Calendar.HOUR字段(取值范围0-11),必须同步给Calendar.AM_PM字段设置对应的标记,不然还是会出现AM/PM识别错的问题,写法参考:
val hour12 = hourOfDay % 12 val period = if (hourOfDay < 12) Calendar.AM else Calendar.PM cal.set(Calendar.HOUR, hour12) cal.set(Calendar.AM_PM, period)
内容的提问来源于stack exchange,提问作者Muhammad Sajid
相关产品推荐
相关产品推荐

