iOS Safari中Javascript日期格式化返回NaN(React天气应用故障)
问题根因
这是iOS Safari浏览器的Date构造函数的字符串格式兼容性问题:
OpenWeatherMap接口返回的dt_txt字段格式为YYYY-MM-DD HH:MM:SS,Chrome等PC端浏览器支持这种用空格分隔日期和时间的写法,但Safari仅兼容ISO 8601规范的YYYY-MM-DDTHH:MM:SS格式(需将日期和时间之间的空格替换为T)。
你直接将dt_txt传入new Date()在Safari中会生成Invalid Date对象,后续调用getMonth()、getDay()这类方法就会返回NaN,触发你自定义的错误提示。
解决方案
方案1:转换日期字符串格式(快速修复)
修改formattedDateTime和formattedWeekDay两个工具函数,传入Date构造函数前先替换日期字符串中的空格为T:
function formattedDateTime(dateTimeText = '', lang = 'en', formattingMonthFunction = monthName) { // 替换空格为T适配Safari日期格式要求 const safeDateStr = dateTimeText.replace(' ', 'T'); const date = new Date(safeDateStr); // 原有逻辑保持不变 const month = formattingMonthFunction(date.getMonth(), lang); const day = date.getDate(); const hours = date.getHours(); const minutes = date.getMinutes(); return `${month} ${day}, ${hours === 0 ? '00' : hours}:${minutes < 10 ? '0' + minutes : minutes}`; } function formattedWeekDay(dateTimeText = '', lang = 'en', formattingFunction = weekdays) { const safeDateStr = dateTimeText.replace(' ', 'T'); const date = new Date(safeDateStr); return formattingFunction(date.getDay(), lang); }
方案2:使用时间戳(更稳妥,推荐)
OpenWeatherMap返回的每一条天气数据都自带Unix秒级时间戳字段dt,所有浏览器都完美支持时间戳生成日期对象,不需要处理字符串格式兼容问题:
修改Clean5DaysForecastData函数中传参逻辑,直接传递时间戳给格式化函数:
export function Clean5DaysForecastData(data, tempUnit = 'C', lang = 'en', formattingCityFunction = formattedCity) { const city = formattingCityFunction(data.city); const dataLength = data.list.length; const filteredList = []; for (let index = 0; index < dataLength; index += 8) { const item = data.list[index]; const singleData = {}; singleData['description'] = firstCharToUpper(item.weather[0].description); singleData['temperature'] = formattedTemperature(item.main.temp, tempUnit); // 传入秒级时间戳转成毫秒,后续格式化函数直接用时间戳生成Date对象 singleData['dateTime'] = formattedDateTime(item.dt * 1000, lang); singleData['weekDay'] = formattedWeekDay(item.dt * 1000, lang); singleData['icon'] = item.weather[0].icon; filteredList.push(singleData); } return [city, filteredList]; }
对应的格式化函数不需要再处理字符串,直接用传入的时间戳生成Date对象即可:
function formattedDateTime(timestamp = 0, lang = 'en', formattingMonthFunction = monthName) { const date = new Date(timestamp); // 原有逻辑保持不变 } function formattedWeekDay(timestamp = 0, lang = 'en', formattingFunction = weekdays) { const date = new Date(timestamp); // 原有逻辑保持不变 }
两种方案修改后PC端和iOS端都可以正常运行,方案2彻底规避了日期字符串格式的兼容性风险,更推荐使用。
内容的提问来源于stack exchange,提问作者elG
相关产品推荐
相关产品推荐

