尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Java实现列车时刻表数据处理:从时间格式化到业务逻辑完整实战

Java实现列车时刻表数据处理:从时间格式化到业务逻辑完整实战
📅 发布时间:2026/7/18 17:08:05

最近在开发铁路调度系统时,经常需要处理列车时刻表数据,其中列车发车时间的计算和格式化是个关键需求。今天我们就来深入探讨如何用Java实现"D3519包头站发车"这类列车时刻信息的处理,从基础的时间格式化到完整的业务逻辑实现。

1. 列车时刻数据处理背景

1.1 业务场景分析

在铁路运输系统中,列车时刻表数据包含丰富的业务信息。以"D3519包头站发车"为例,这不仅仅是一个简单的字符串,而是包含了车次号、站点名称、业务动作等多个维度的信息。在实际业务中,我们需要准确解析这些信息,并关联具体的发车时间、到站时间等时间数据。

1.2 技术挑战

处理列车时刻数据面临几个主要挑战:时间格式的标准化、多时区处理、业务逻辑的复杂性等。特别是当系统需要处理全国范围的列车数据时,时区转换和夏令时等问题都需要仔细考虑。

2. 环境准备与依赖配置

2.1 开发环境要求

  • JDK 8或更高版本
  • Maven 3.6+
  • IDE:IntelliJ IDEA或Eclipse

2.2 Maven依赖配置

在pom.xml中添加必要依赖:

<dependencies> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.10.14</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> </dependencies>

3. 核心数据模型设计

3.1 列车时刻实体类设计

首先设计一个完整的列车时刻数据模型:

public class TrainSchedule { private String trainNumber; // 车次号,如D3519 private String stationName; // 站点名称,如包头站 private String actionType; // 动作类型:发车、到站等 private LocalDateTime scheduleTime; // 计划时间 private TimeZone timeZone; // 时区信息 // 构造函数 public TrainSchedule(String trainNumber, String stationName, String actionType, LocalDateTime scheduleTime) { this.trainNumber = trainNumber; this.stationName = stationName; this.actionType = actionType; this.scheduleTime = scheduleTime; this.timeZone = TimeZone.getDefault(); } // getter和setter方法 public String getTrainNumber() { return trainNumber; } public void setTrainNumber(String trainNumber) { this.trainNumber = trainNumber; } public String getStationName() { return stationName; } public void setStationName(String stationName) { this.stationName = stationName; } public String getActionType() { return actionType; } public void setActionType(String actionType) { this.actionType = actionType; } public LocalDateTime getScheduleTime() { return scheduleTime; } public void setScheduleTime(LocalDateTime scheduleTime) { this.scheduleTime = scheduleTime; } public TimeZone getTimeZone() { return timeZone; } public void setTimeZone(TimeZone timeZone) { this.timeZone = timeZone; } }

3.2 时间格式化工具类

创建专门的时间格式化工具类来处理各种时间格式:

public class TimeFormatUtil { private static final DateTimeFormatter STANDARD_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private static final DateTimeFormatter SIMPLE_FORMATTER = DateTimeFormatter.ofPattern("HH:mm"); /** * 标准化时间格式输出 */ public static String formatStandardTime(LocalDateTime dateTime) { return dateTime.format(STANDARD_FORMATTER); } /** * 简单时间格式(仅小时分钟) */ public static String formatSimpleTime(LocalDateTime dateTime) { return dateTime.format(SIMPLE_FORMATTER); } /** * 解析字符串时间为LocalDateTime */ public static LocalDateTime parseTime(String timeString) { try { // 尝试解析完整格式 return LocalDateTime.parse(timeString, STANDARD_FORMATTER); } catch (DateTimeParseException e) { // 解析简单格式(需要结合当前日期) LocalTime localTime = LocalTime.parse(timeString, SIMPLE_FORMATTER); return LocalDateTime.of(LocalDate.now(), localTime); } } }

4. 业务逻辑实现

4.1 列车时刻解析器

实现一个强大的解析器来处理各种格式的列车时刻信息:

public class TrainScheduleParser { /** * 解析列车时刻信息字符串 * 支持格式:"D3519包头站发车 08:30" */ public static TrainSchedule parseScheduleInfo(String scheduleInfo) { if (scheduleInfo == null || scheduleInfo.trim().isEmpty()) { throw new IllegalArgumentException("时刻信息不能为空"); } // 使用正则表达式解析字符串 Pattern pattern = Pattern.compile("([A-Z]\\d+)(.+?)(发车|到站)\\s*(\\d{1,2}:\\d{2})"); Matcher matcher = pattern.matcher(scheduleInfo); if (matcher.find()) { String trainNumber = matcher.group(1); // 车次号 String stationName = matcher.group(2).trim(); // 站点名称 String actionType = matcher.group(3); // 动作类型 String timeString = matcher.group(4); // 时间字符串 LocalDateTime scheduleTime = TimeFormatUtil.parseTime(timeString); return new TrainSchedule(trainNumber, stationName, actionType, scheduleTime); } else { throw new IllegalArgumentException("无法解析的列车时刻格式: " + scheduleInfo); } } /** * 生成标准化的显示信息 */ public static String generateDisplayInfo(TrainSchedule schedule) { String timeStr = TimeFormatUtil.formatSimpleTime(schedule.getScheduleTime()); return String.format("%s%s%s %s", schedule.getTrainNumber(), schedule.getStationName(), schedule.getActionType(), timeStr); } }

4.2 时刻表管理服务

实现一个完整的时刻表管理服务:

@Service public class TrainScheduleService { private List<TrainSchedule> schedules = new ArrayList<>(); /** * 添加列车时刻 */ public void addSchedule(TrainSchedule schedule) { // 验证数据完整性 validateSchedule(schedule); schedules.add(schedule); // 按时间排序 schedules.sort(Comparator.comparing(TrainSchedule::getScheduleTime)); } /** * 根据车次号查询时刻信息 */ public List<TrainSchedule> getSchedulesByTrainNumber(String trainNumber) { return schedules.stream() .filter(schedule -> schedule.getTrainNumber().equals(trainNumber)) .collect(Collectors.toList()); } /** * 查询指定时间范围内的时刻信息 */ public List<TrainSchedule> getSchedulesInTimeRange(LocalDateTime start, LocalDateTime end) { return schedules.stream() .filter(schedule -> !schedule.getScheduleTime().isBefore(start) && !schedule.getScheduleTime().isAfter(end)) .collect(Collectors.toList()); } /** * 数据验证 */ private void validateSchedule(TrainSchedule schedule) { if (schedule.getTrainNumber() == null || schedule.getTrainNumber().isEmpty()) { throw new IllegalArgumentException("车次号不能为空"); } if (schedule.getStationName() == null || schedule.getStationName().isEmpty()) { throw new IllegalArgumentException("站点名称不能为空"); } if (schedule.getScheduleTime() == null) { throw new IllegalArgumentException("计划时间不能为空"); } } }

5. 完整实战示例

5.1 创建测试数据

编写一个完整的演示程序:

public class TrainScheduleDemo { public static void main(String[] args) { // 创建时刻表服务 TrainScheduleService scheduleService = new TrainScheduleService(); // 解析并添加示例数据 String[] scheduleInfos = { "D3519包头站发车 08:30", "D3519呼和浩特站到站 10:15", "D3520北京站发车 14:20", "D3520天津站到站 16:05" }; for (String info : scheduleInfos) { try { TrainSchedule schedule = TrainScheduleParser.parseScheduleInfo(info); scheduleService.addSchedule(schedule); System.out.println("成功添加: " + TrainScheduleParser.generateDisplayInfo(schedule)); } catch (Exception e) { System.err.println("解析失败: " + info + ", 错误: " + e.getMessage()); } } // 查询D3519车次的全部时刻 System.out.println("\n=== D3519车次时刻表 ==="); List<TrainSchedule> d3519Schedules = scheduleService.getSchedulesByTrainNumber("D3519"); for (TrainSchedule schedule : d3519Schedules) { System.out.println(TrainScheduleParser.generateDisplayInfo(schedule)); } // 查询时间范围内的时刻 System.out.println("\n=== 上午时刻表(08:00-12:00)==="); LocalDateTime morningStart = LocalDateTime.of(LocalDate.now(), LocalTime.of(8, 0)); LocalDateTime morningEnd = LocalDateTime.of(LocalDate.now(), LocalTime.of(12, 0)); List<TrainSchedule> morningSchedules = scheduleService.getSchedulesInTimeRange(morningStart, morningEnd); for (TrainSchedule schedule : morningSchedules) { System.out.println(TrainScheduleParser.generateDisplayInfo(schedule)); } } }

5.2 运行结果示例

运行上述程序,预期输出如下:

成功添加: D3519包头站发车 08:30 成功添加: D3519呼和浩特站到站 10:15 成功添加: D3520北京站发车 14:20 成功添加: D3520天津站到站 16:05 === D3519车次时刻表 === D3519包头站发车 08:30 D3519呼和浩特站到站 10:15 === 上午时刻表(08:00-12:00)=== D3519包头站发车 08:30 D3519呼和浩特站到站 10:15

6. 高级功能实现

6.1 时区处理增强

在实际铁路系统中,需要处理跨时区的时刻转换:

public class TimeZoneConverter { /** * 转换时区 */ public static LocalDateTime convertTimeZone(LocalDateTime originalTime, TimeZone fromZone, TimeZone toZone) { ZonedDateTime fromZoned = ZonedDateTime.of(originalTime, ZoneId.of(fromZone.getID())); ZonedDateTime toZoned = fromZoned.withZoneSameInstant(ZoneId.of(toZone.getID())); return toZoned.toLocalDateTime(); } /** * 获取站点所在时区 */ public static TimeZone getStationTimeZone(String stationName) { // 实际项目中这里可以从数据库或配置文件中获取 Map<String, String> stationTimeZones = new HashMap<>(); stationTimeZones.put("包头站", "Asia/Shanghai"); stationTimeZones.put("呼和浩特站", "Asia/Shanghai"); stationTimeZones.put("北京站", "Asia/Shanghai"); String timeZoneId = stationTimeZones.getOrDefault(stationName, "Asia/Shanghai"); return TimeZone.getTimeZone(timeZoneId); } }

6.2 JSON序列化支持

为了方便API接口使用,添加JSON序列化支持:

public class TrainScheduleSerializer { private static final ObjectMapper objectMapper = new ObjectMapper(); static { // 注册JavaTime模块以支持LocalDateTime序列化 objectMapper.registerModule(new JavaTimeModule()); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); } /** * 序列化为JSON字符串 */ public static String toJson(TrainSchedule schedule) throws JsonProcessingException { return objectMapper.writeValueAsString(schedule); } /** * 从JSON字符串反序列化 */ public static TrainSchedule fromJson(String json) throws JsonProcessingException { return objectMapper.readValue(json, TrainSchedule.class); } }

7. 异常处理与数据验证

7.1 自定义异常类

定义业务相关的异常类:

public class TrainScheduleException extends RuntimeException { private final ErrorCode errorCode; public TrainScheduleException(ErrorCode errorCode, String message) { super(message); this.errorCode = errorCode; } public TrainScheduleException(ErrorCode errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = errorCode; } public ErrorCode getErrorCode() { return errorCode; } } public enum ErrorCode { INVALID_TRAIN_NUMBER("无效的车次号格式"), INVALID_TIME_FORMAT("无效的时间格式"), STATION_NOT_FOUND("站点不存在"), DUPLICATE_SCHEDULE("重复的时刻记录"); private final String description; ErrorCode(String description) { this.description = description; } public String getDescription() { return description; } }

7.2 数据验证增强

完善数据验证逻辑:

public class ScheduleValidator { /** * 验证车次号格式 */ public static boolean isValidTrainNumber(String trainNumber) { if (trainNumber == null) return false; // 车次号格式:字母开头,后跟数字,如D3519、G1234等 return trainNumber.matches("[A-Z]\\d+"); } /** * 验证时间合理性 */ public static boolean isValidScheduleTime(LocalDateTime time) { if (time == null) return false; // 不能是过去的时间(允许当天的未来时间) LocalDateTime now = LocalDateTime.now(); return !time.isBefore(now.with(LocalTime.MIN)); // 允许当天的时间 } /** * 完整验证 */ public static void validateComplete(TrainSchedule schedule) { if (!isValidTrainNumber(schedule.getTrainNumber())) { throw new TrainScheduleException(ErrorCode.INVALID_TRAIN_NUMBER, "无效车次号: " + schedule.getTrainNumber()); } if (!isValidScheduleTime(schedule.getScheduleTime())) { throw new TrainScheduleException(ErrorCode.INVALID_TIME_FORMAT, "无效时间: " + schedule.getScheduleTime()); } } }

8. 单元测试编写

8.1 解析器测试

编写完整的单元测试确保代码质量:

public class TrainScheduleParserTest { @Test public void testParseValidSchedule() { String scheduleInfo = "D3519包头站发车 08:30"; TrainSchedule schedule = TrainScheduleParser.parseScheduleInfo(scheduleInfo); assertEquals("D3519", schedule.getTrainNumber()); assertEquals("包头站", schedule.getStationName()); assertEquals("发车", schedule.getActionType()); assertEquals(LocalTime.of(8, 30), schedule.getScheduleTime().toLocalTime()); } @Test public void testParseInvalidFormat() { String invalidInfo = "无效的格式"; assertThrows(IllegalArgumentException.class, () -> { TrainScheduleParser.parseScheduleInfo(invalidInfo); }); } @Test public void testGenerateDisplayInfo() { TrainSchedule schedule = new TrainSchedule("D3519", "包头站", "发车", LocalDateTime.of(2024, 1, 1, 8, 30)); String displayInfo = TrainScheduleParser.generateDisplayInfo(schedule); assertEquals("D3519包头站发车 08:30", displayInfo); } }

8.2 服务层测试

测试业务逻辑的正确性:

public class TrainScheduleServiceTest { private TrainScheduleService service; @BeforeEach public void setUp() { service = new TrainScheduleService(); } @Test public void testAddAndRetrieveSchedules() { TrainSchedule schedule1 = new TrainSchedule("D3519", "包头站", "发车", LocalDateTime.of(2024, 1, 1, 8, 30)); TrainSchedule schedule2 = new TrainSchedule("D3519", "呼和浩特站", "到站", LocalDateTime.of(2024, 1, 1, 10, 15)); service.addSchedule(schedule1); service.addSchedule(schedule2); List<TrainSchedule> schedules = service.getSchedulesByTrainNumber("D3519"); assertEquals(2, schedules.size()); // 验证按时间排序 assertTrue(schedules.get(0).getScheduleTime().isBefore(schedules.get(1).getScheduleTime())); } }

9. 性能优化建议

9.1 数据存储优化

对于大规模的时刻表数据,建议使用数据库存储并建立合适的索引:

CREATE TABLE train_schedule ( id BIGINT AUTO_INCREMENT PRIMARY KEY, train_number VARCHAR(20) NOT NULL, station_name VARCHAR(100) NOT NULL, action_type VARCHAR(10) NOT NULL, schedule_time DATETIME NOT NULL, time_zone VARCHAR(50) NOT NULL, INDEX idx_train_number (train_number), INDEX idx_schedule_time (schedule_time), INDEX idx_station_time (station_name, schedule_time) );

9.2 缓存策略

对于频繁查询的数据,可以引入缓存机制:

@Service public class CachedTrainScheduleService { private final TrainScheduleService delegate; private final Cache<String, List<TrainSchedule>> cache; public CachedTrainScheduleService(TrainScheduleService delegate) { this.delegate = delegate; this.cache = Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000) .build(); } public List<TrainSchedule> getSchedulesByTrainNumber(String trainNumber) { return cache.get(trainNumber, key -> delegate.getSchedulesByTrainNumber(key)); } }

10. 生产环境注意事项

10.1 配置管理

将易变的配置外化:

# application.properties train.schedule.timezone.default=Asia/Shanghai train.schedule.cache.enabled=true train.schedule.cache.duration=10m

10.2 日志记录

添加详细的日志记录以便排查问题:

@Slf4j public class TrainScheduleService { public void addSchedule(TrainSchedule schedule) { try { validateSchedule(schedule); schedules.add(schedule); schedules.sort(Comparator.comparing(TrainSchedule::getScheduleTime)); log.info("成功添加列车时刻: {}", TrainScheduleParser.generateDisplayInfo(schedule)); } catch (Exception e) { log.error("添加列车时刻失败: {}", schedule, e); throw e; } } }

10.3 监控指标

添加业务监控指标:

@Component public class ScheduleMetrics { private final MeterRegistry meterRegistry; private final Counter addScheduleCounter; private final Counter parseErrorCounter; public ScheduleMetrics(MeterRegistry meterRegistry) { this.meterRegistry = meterRegistry; this.addScheduleCounter = Counter.builder("train.schedule.add") .description("添加列车时刻计数") .register(meterRegistry); this.parseErrorCounter = Counter.builder("train.schedule.parse.error") .description("解析错误计数") .register(meterRegistry); } }

通过本文的完整实现,我们建立了一个健壮的列车时刻处理系统,能够准确解析"D3519包头站发车"这类业务信息,并提供完整的增删改查功能。在实际项目中,可以根据具体需求进一步扩展功能,如实时数据同步、多语言支持、移动端适配等。

相关新闻

  • 济南哪家民办中专学校比较不错
  • 强力磁铁高吸力耐用 工业通用强磁 源头厂家定制 - 优企甄选
  • 2026济南屋顶漏水维修怎么做?对比3家正规公司报价与施工方案(7月实测) - 吉林同城获客

最新新闻

  • 2026揭阳黄金回收白银回收铂金回收中检持证鉴定师铂金银饰高价回收门店联系方式推荐
  • 晶振原理与应用:电子设备频率稳定的核心技术
  • 2026文山别墅自建施工怎么选?TOP 砖混 + 框架 + 轻钢 + 庭院一体化 附电话地址 - 中检检测集团
  • SolidWorks:安装教程
  • 2026年制造业还有必要上CPQ吗?梅施CPQ实测优缺点、适用人群全解析
  • 2026三明雨棚搭建怎么选?TOP 铝合金 + 玻璃 + 耐力板 + 上门测量安装 附电话地址 - 科信检测

日新闻

  • 宝珀中国官方售后服务中心|官方热线和维修地址权威信息声明(2026年7月更新) - 宝珀官方售后服务中心
  • # 2026年北京知识产权律师推荐怎么选?看这五点关键不踩雷 - 本地品牌推荐
  • 2026实测教程:生成的拼豆图纸不满意怎么修改才省事 - 省事研究所

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号