refactor(flight-state): 按 flight-state.md 审计定稿全量重构脚手架与 SQL (ACM2-31)
- SQL 基线 V1__flight_state_baseline.sql 整体取代 V1.0.0–V1.4.0: PIPELINE_LOCK/PROC_STATE/MSG_EVENT/REQ_TRACK/BACKFILL_TODO/FLIGHT_SCHD + 8 张资源明细表 + FLIGHT_ROUTE_POINT + SCHD_SNAP_LOG 留痕层 - 废除 FDAY 日代/SCHD_GEN/名单差删:OPERATION_DAY 不可变(应用层校验 + 条件更新强化 §7.4),STATE 仅 ACTIVE/DELETED,物理清除只在历史归档后 - 处理器化:applyScheduleRecords(§5.1 七步同一事务,重放判定/整包 DEAD(PROTOCOL)/归属冲突不落地)+ FLOP/FDEL/ADFT(tombstone 仅 ACTIVE→DELETED,重复 FDEL 幂等不推进版本) - 投递:KAFKA_SCHD 同 FLID 按最新 STATE_VERSION 合并,被压掉事件关闭, TOMBSTONE 发 null 值消息(键缺失=删除旧值 §7.3) - 回填待办改为业务事务内预登记,消除提交后写待办的崩溃窗口(§7.2/§10) - XML 解码改为 jackson-dataformat-xml 数据类直接映射(SIS 信封强类型, FLTR 开放标签泛型承载) - 历史归档/物理清除顺序不可颠倒:归档确认成功集才物理删除,未接通删 0 条 - 移除 PUMP_JOB 队列/ReferenceService/FlightStoreDiffTool 等旧机制与测试, 新增运营日/引擎/快照/FDEL/归档顺序不变性回归测试
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package com.gzzn.omms.msgexchange.domain
|
||||
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
|
||||
/**
|
||||
* 运营日计算(docs/flight-state.md §3.5):由计划运行时间字段 SODT(ddMMMyyHHmm)
|
||||
* 与机场时区计算;切日边界业务配置——默认 0 点为占位,待业务确认(§10)。
|
||||
*/
|
||||
class OperationDayCalculator(
|
||||
zone: ZoneId,
|
||||
cutoffHour: Int,
|
||||
) {
|
||||
private val zone: ZoneId = zone
|
||||
/** 切日边界:SODT 本地时刻早于该小时的归属前一运营日(0–23,越界按 0)。 */
|
||||
private val cutoffHour: Int = cutoffHour.coerceIn(0, 23)
|
||||
|
||||
/** SODT → 运营日;输入 null/空/非法返回 null(不抛异常,调用方按"运营日不可计算"处理)。 */
|
||||
fun compute(sodt: String?): LocalDate? {
|
||||
if (sodt.isNullOrBlank()) return null
|
||||
val local = parseSodt(sodt.trim()) ?: return null
|
||||
val day = local.atZone(zone).toLocalDate()
|
||||
return if (local.hour < cutoffHour) day.minusDays(1) else day
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* SIS SODT 线格式:ddMMMyyHHmm(如 15DEC031723),月份英文三字母、大小写不敏感。
|
||||
* 两位年显式按 2000 基准展开(java.time 的 yy reduced-value 解析跨实现不一致,
|
||||
* 显式展开保证 AODB 侧年份窗口唯一口径;基准年待真实报文验收确认 §10)。
|
||||
*/
|
||||
private val SODT_REGEX = Regex("(\\d{1,2})([A-Za-z]{3})(\\d{2})(\\d{2})(\\d{2})")
|
||||
|
||||
private val MONTHS = mapOf(
|
||||
"JAN" to 1, "FEB" to 2, "MAR" to 3, "APR" to 4, "MAY" to 5, "JUN" to 6,
|
||||
"JUL" to 7, "AUG" to 8, "SEP" to 9, "OCT" to 10, "NOV" to 11, "DEC" to 12,
|
||||
)
|
||||
|
||||
internal fun parseSodt(raw: String): LocalDateTime? {
|
||||
val m = SODT_REGEX.matchEntire(raw.uppercase()) ?: return null
|
||||
val (d, mon, yy, hh, mm) = m.destructured
|
||||
val month = MONTHS[mon] ?: return null
|
||||
return runCatching {
|
||||
LocalDateTime.of(2000 + yy.toInt(), month, d.toInt(), hh.toInt(), mm.toInt())
|
||||
}.getOrNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user