Flutter真机中_pickedTime.format(context)转换TimeOfDay为String报错求助
问题原因
错误Trying to read from 08:43 at position 6是因为真实设备与模拟器的区域设置不同,导致TimeOfDay.format(context)返回的时间字符串格式不一致:
- 模拟器可能返回带AM/PM的12小时制格式(如
08:43 AM) - 真实设备可能返回不带AM/PM的24小时制格式(如
08:43)
当你用DateFormat.jm()(专门解析带AM/PM的12小时制字符串)去解析24小时制字符串时,解析器会尝试读取AM/PM部分(对应字符串索引6的位置),但24小时制字符串长度不足,因此抛出索引越界错误。
另外,代码还存在空指针隐患:用户取消时间选择时pickedTime为null,直接调用pickedTime.format(context)会崩溃。
解决方案
1. 取消依赖系统区域的时间格式化,改用自定义固定格式
避免TimeOfDay.format(context)带来的格式差异,自己实现固定格式的时间转换:
// 自定义12小时制格式化(带AM/PM) String formatTimeOfDay(TimeOfDay time) { final period = time.hour >= 12 ? 'PM' : 'AM'; final displayHour = time.hour % 12 == 0 ? 12 : time.hour % 12; return '${displayHour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')} $period'; } // 或者自定义24小时制格式化 String formatTimeOfDay24(TimeOfDay time) { return '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}'; }
2. 修复空指针问题,修改_getTimeFromUser方法
先判断用户是否取消选择,再处理时间格式化:
_getTimeFromUser({required bool isStartTime}) async { final pickedTime = await _showTimePicker(); if (pickedTime == null) { debugPrint('Time Cancelled'); return; } // 使用自定义格式化方法替代系统format final formattedTime = formatTimeOfDay(pickedTime); setState(() { if (isStartTime) { _startTime = formattedTime; } else { _endTime = formattedTime; } }); }
3. 统一时间解析逻辑
如果task.startTime是用自定义格式生成的,解析时要匹配对应的DateFormat:
- 若用12小时制带AM/PM,继续用
DateFormat.jm()解析 - 若用24小时制,改用
DateFormat.Hm()解析
修改解析代码:
// 假设task.startTime是24小时制格式,用DateFormat.Hm()解析 DateTime date = DateFormat.Hm().parse(task.startTime); final myTime = DateFormat("HH:mm").format(date); notificationService.scheduleNotification( hour: int.parse(myTime.split(":")[0]), minutes: int.parse(myTime.split(":")[1]), task: task );
4. 优化_showTimePicker的初始化逻辑
确保初始化TimeOfDay时,拆分逻辑匹配自定义格式:
// 针对12小时制格式拆分(如"08:43 AM") _showTimePicker() { final timeParts = _startTime.split(':'); final hourPart = timeParts[0]; final minutePeriodPart = timeParts[1].split(' '); final minutePart = minutePeriodPart[0]; final period = minutePeriodPart[1]; int hour = int.parse(hourPart); if (period == 'PM' && hour != 12) { hour += 12; } else if (period == 'AM' && hour == 12) { hour = 0; } return showTimePicker( context: context, initialEntryMode: TimePickerEntryMode.input, initialTime: TimeOfDay(hour: hour, minute: int.parse(minutePart)), ); } // 如果用24小时制格式,拆分更简单: // _showTimePicker() { // final timeParts = _startTime.split(':'); // return showTimePicker( // context: context, // initialEntryMode: TimePickerEntryMode.input, // initialTime: TimeOfDay( // hour: int.parse(timeParts[0]), // minute: int.parse(timeParts[1]), // ), // ); // }
总结
核心思路是统一时间的格式化和解析规则,避免依赖系统区域设置带来的格式差异,同时修复空指针隐患,这样无论在真实设备还是模拟器上,时间处理逻辑都会保持一致。
内容的提问来源于stack exchange,提问作者Emeka Jide
相关产品推荐
相关产品推荐

