Cadence Workflow ZonedDateTime入参UTC时区转Z标识问题咨询
时区转换行为原因
这个转换是Cadence默认的参数序列化/反序列化逻辑触发的,具体分为两个核心环节:
- Jackson序列化的默认规则
Cadence默认使用Jackson作为参数的序列化框架,针对java.time.ZonedDateTime类型,Jackson内置的JavaTimeModule默认遵循ISO 8601标准输出,UTC零时区的官方标准简写就是Z,因此在客户端启动工作流、把入参序列化为JSON存储到Cadence服务端时,原本ZoneId为UTC的时间会被序列化为带Z后缀的ISO时间字符串,不会保留UTC标识。 - Cadence反序列化的默认规则
工作流执行时,Cadence会把服务端存储的序列化JSON反序列化为对应的参数对象,此时Jackson默认会把ISO时间字符串中的Z后缀解析为ZoneId为Z的实例,而不是还原为UTC的ZoneId。二者本质偏移量完全一致,时间逻辑等价,仅ZoneId的字符串标识存在差异。
如果需要保留原有的UTCZoneId标识,可以自定义构建Cadence WorkflowClient时传入配置了自定义ZonedDateTime序列化规则的ObjectMapper,强制将零时区的ZoneId统一映射为UTC即可。
// 自定义序列化配置示例 val customMapper = ObjectMapper() .registerModule(JavaTimeModule()) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) // 自定义ZonedDateTime序列化器,强制零时区输出UTC标识 .addSerializer(ZonedDateTime::class.java, object : StdSerializer<ZonedDateTime>(ZonedDateTime::class.java) { override fun serialize(value: ZonedDateTime, gen: JsonGenerator, provider: SerializerProvider) { val zone = if (value.zone == ZoneId.of("Z")) ZoneId.of("UTC") else value.zone gen.writeString(value.withZoneSameInstant(zone).format(DateTimeFormatter.ISO_ZONED_DATE_TIME)) } }) // 对应自定义反序列化器 .addDeserializer(ZonedDateTime::class.java, object : StdDeserializer<ZonedDateTime>(ZonedDateTime::class.java) { override fun deserialize(p: JsonParser, ctxt: DeserializationContext): ZonedDateTime { val time = ZonedDateTime.parse(p.text, DateTimeFormatter.ISO_ZONED_DATE_TIME) return if (time.zone == ZoneId.of("Z")) time.withZoneSameInstant(ZoneId.of("UTC")) else time } }) // 构建WorkflowClient时指定自定义mapper val workflowClient = WorkflowClient.newInstance(service, WorkflowClientOptions.newBuilder() .setDataConverter(JacksonJsonDataConverter(customMapper)) .build())
内容的提问来源于stack exchange,提问作者user12488846
相关产品推荐
相关产品推荐

