使用ical4j指定Australia/Lord_Howe时区时出现日期解析异常
ical4j在Australia/Lord_Howe时区下日期解析异常解决方案
运行以下代码时,仅指定Australia/Lord_Howe时区会抛出日期解析异常,其他时区均正常工作,期望生成DTSTART;TZID=Australia/Lord_Howe:20221207T170935格式的DtStart值。
异常代码
public class Timezone { public static void main(String[] args) { TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry(); TimeZone tz; LocalDateTime now = LocalDateTime.now(); final DateTimeFormatter ICS_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss"); //tz = registry.getTimeZone("Asia/Calcutta"); tz = registry.getTimeZone("Australia/Lord_Howe"); DtStart dtstart; try { dtstart = new DtStart(now.format(ICS_DATE_FORMATTER),tz); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
报错信息
java.text.ParseException: Unparseable date: "20221207T170935" at java.base/java.text.DateFormat.parse(DateFormat.java:395) at net.fortuna.ical4j.model.DateTime.setTime(DateTime.java:418) at net.fortuna.ical4j.model.DateTime.<init>(DateTime.java:325) at net.fortuna.ical4j.model.property.DateProperty.setValue(DateProperty.java:137) at net.fortuna.ical4j.model.property.DtStart.<init>(DtStart.java:146) at Timezone.main(Timezone.java:33)
问题原因
Australia/Lord_Howe时区的夏令时规则特殊,标准时区偏移为+10:30,夏令时偏移为+11:00。当ical4j尝试将不带时区信息的日期字符串结合该时区解析时,默认的严格解析模式无法适配这种非整小时的偏移规则,从而抛出解析异常。
解决方案
方案1:直接使用带时区的日期对象构造DtStart
跳过字符串转换环节,直接构造带目标时区的日期对象,避免解析冲突:
public class Timezone { public static void main(String[] args) { TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry(); TimeZone tz = registry.getTimeZone("Australia/Lord_Howe"); // 直接生成带目标时区的ical4j DateTime对象 DateTime icalDateTime = new DateTime(java.util.Calendar.getInstance(tz)); DtStart dtstart; try { dtstart = new DtStart(icalDateTime); // 验证输出结果 System.out.println(dtstart); } catch (Exception e) { e.printStackTrace(); } } }
方案2:启用ical4j宽松解析模式
通过系统属性开启ical4j的宽松解析,适配特殊时区的偏移规则:
public class Timezone { public static void main(String[] args) { // 启用宽松解析模式 System.setProperty("net.fortuna.ical4j.parser.lenient", "true"); TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry(); TimeZone tz; LocalDateTime now = LocalDateTime.now(); final DateTimeFormatter ICS_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss"); tz = registry.getTimeZone("Australia/Lord_Howe"); DtStart dtstart; try { dtstart = new DtStart(now.format(ICS_DATE_FORMATTER),tz); System.out.println(dtstart); } catch (Exception e) { e.printStackTrace(); } } }
内容的提问来源于stack exchange,提问作者Swati Satrusalya
相关产品推荐
相关产品推荐

