Kotlin解析俄文日期失败:如何正确解析"28 фев. 2019"?
俄文日期解析失败问题排查与解决
问题描述
尝试用Kotlin代码解析多语言日期格式时,俄文日期"27 апр. 2018"和"24 мая. 2013"能正常解析,但"28 фев. 2019"始终解析失败。运行环境为Java 17.0.4.1,报错信息如下:
Parse failed - java.time.format.DateTimeParseException: Text '28 фев. 2019' could not be parsed at index 3
用户核心代码示例:
import java.time.LocalDate import java.time.format.DateTimeFormatter import java.util.* println("System.getProperty - " + System.getProperty("java.version")); println("Runtime.version - " + Runtime.version()); val dateString = "28 фев. 2019" sequenceOf( "ru-RU", // Russian "sr", // Serbian ).forEach { val format = DateTimeFormatter.ofPattern("d MMM. yyyy") .withLocale(Locale.forLanguageTag(it)) try { println("Parse successful - " + LocalDate.parse(dateString, format)) } catch (e: Exception) { println("Parse failed - " + e) } }
问题原因
俄语中“二月”的标准缩写在Java的DateTimeFormatter默认配置里是"февр."(4个字母加句号),但待解析的日期里用的是"фев."(3个字母加句号),两者长度不匹配,导致解析失败。而其他月份(如四月апр.、五月мая.)的缩写与系统默认值一致,所以能正常解析。
解决方案
方案一:自定义月份缩写映射
创建包含目标缩写的映射表,覆盖DateTimeFormatter的默认月份解析规则:
import java.time.LocalDate import java.time.Month import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatterBuilder import java.util.* fun main() { println("System.getProperty - " + System.getProperty("java.version")) println("Runtime.version - " + Runtime.version()) val dateString = "28 фев. 2019" val ruLocale = Locale.forLanguageTag("ru-RU") // 自定义俄文月份缩写与对应月份的映射 val monthAbbrMap = mapOf( "янв." to Month.JANUARY, "фев." to Month.FEBRUARY, "мар." to Month.MARCH, "апр." to Month.APRIL, "мая." to Month.MAY, "июн." to Month.JUNE, "июл." to Month.JULY, "авг." to Month.AUGUST, "сен." to Month.SEPTEMBER, "окт." to Month.OCTOBER, "ноя." to Month.NOVEMBER, "дек." to Month.DECEMBER ) val formatter = DateTimeFormatterBuilder() .appendPattern("d ") .appendText(Month.MONTH_OF_YEAR, monthAbbrMap) .appendPattern(" yyyy") .toFormatter(ruLocale) try { println("Parse successful - " + LocalDate.parse(dateString, formatter)) } catch (e: Exception) { println("Parse failed - " + e) } }
方案二:启用宽松解析模式
通过DateTimeFormatterBuilder设置宽松解析,允许部分匹配系统默认的缩写:
import java.time.LocalDate import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatterBuilder import java.util.* fun main() { println("System.getProperty - " + System.getProperty("java.version")) println("Runtime.version - " + Runtime.version()) val dateString = "28 фев. 2019" val ruLocale = Locale.forLanguageTag("ru-RU") val formatter = DateTimeFormatterBuilder() .appendPattern("d MMM. yyyy") .parseLenient() // 启用宽松解析规则 .toFormatter(ruLocale) try { println("Parse successful - " + LocalDate.parse(dateString, formatter)) } catch (e: Exception) { println("Parse failed - " + e) } }
注意:宽松解析可能引入歧义风险,若存在其他类似缩写的日期格式,需谨慎使用。
运行验证
使用方案二的代码运行后,输出结果为:
System.getProperty - 17.0.4.1 Runtime.version - 17.0.4.1+7-b469.62 Parse successful - 2019-02-28
内容的提问来源于stack exchange,提问作者Nebu Pookins
相关产品推荐
相关产品推荐

