Формат времени в UTC

This commit is contained in:
emelianov
2026-06-25 16:21:17 +03:00
parent d0ec0ef754
commit fe54c095ab
164 changed files with 1847 additions and 634 deletions
@@ -0,0 +1,41 @@
package space.nstart.pcp.pcp_mission_planing_service.configuration
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import space.nstart.pcp.pcp_types_lib.utils.UtcDateTimes
import java.time.LocalDateTime
@Configuration
class Jackson2UtcConfiguration {
@Bean
fun jackson2ObjectMapper(): ObjectMapper = jacksonObjectMapper()
.findAndRegisterModules()
.registerModule(utcLocalDateTimeModule())
}
private fun utcLocalDateTimeModule(): SimpleModule = SimpleModule("pcp-mission-planing-service-jackson2-utc-local-date-time")
.addSerializer(LocalDateTime::class.java, Jackson2UtcLocalDateTimeSerializer())
.addDeserializer(LocalDateTime::class.java, Jackson2UtcLocalDateTimeDeserializer())
private class Jackson2UtcLocalDateTimeSerializer : JsonSerializer<LocalDateTime>() {
override fun serialize(value: LocalDateTime, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeString(UtcDateTimes.format(value))
}
}
private class Jackson2UtcLocalDateTimeDeserializer : JsonDeserializer<LocalDateTime>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): LocalDateTime {
val value = p.valueAsString ?: throw IllegalArgumentException("Expected ISO-8601 UTC date-time string")
return UtcDateTimes.parse(value)
}
}
@@ -0,0 +1,55 @@
package space.nstart.pcp.pcp_mission_planing_service.configuration
import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.convert.converter.Converter
import org.springframework.format.FormatterRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import space.nstart.pcp.pcp_types_lib.utils.UtcDateTimes
import tools.jackson.core.JsonGenerator
import tools.jackson.core.JsonParser
import tools.jackson.databind.DeserializationContext
import tools.jackson.databind.SerializationContext
import tools.jackson.databind.deser.std.StdDeserializer
import tools.jackson.databind.module.SimpleModule
import tools.jackson.databind.ser.std.StdSerializer
import java.time.Clock
import java.time.LocalDateTime
@Configuration
class UtcTimeConfiguration : WebMvcConfigurer {
@Bean
fun clock(): Clock = Clock.systemUTC()
@Bean
fun missionPlaningUtcLocalDateTimeCustomizer(): JsonMapperBuilderCustomizer = JsonMapperBuilderCustomizer { builder ->
builder.addModule(
SimpleModule("pcp-mission-planing-service-utc-local-date-time")
.addSerializer(LocalDateTime::class.java, UtcLocalDateTimeSerializer())
.addDeserializer(LocalDateTime::class.java, UtcLocalDateTimeDeserializer())
)
}
override fun addFormatters(registry: FormatterRegistry) {
registry.addConverter(UtcLocalDateTimeQueryParamConverter())
}
}
private class UtcLocalDateTimeQueryParamConverter : Converter<String, LocalDateTime> {
override fun convert(source: String): LocalDateTime = UtcDateTimes.parse(source)
}
private class UtcLocalDateTimeSerializer : StdSerializer<LocalDateTime>(LocalDateTime::class.java) {
override fun serialize(value: LocalDateTime, gen: JsonGenerator, ctxt: SerializationContext) {
gen.writeString(UtcDateTimes.format(value))
}
}
private class UtcLocalDateTimeDeserializer : StdDeserializer<LocalDateTime>(LocalDateTime::class.java) {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): LocalDateTime {
val value = p.valueAsString ?: throw IllegalArgumentException("Expected ISO-8601 UTC date-time string")
return UtcDateTimes.parse(value)
}
}
@@ -13,6 +13,7 @@ import space.nstart.pcp.pcp_types_lib.dto.ballistics.PointViewParamDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.RadioVisibilityAreaDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SquareViewParamDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SquareViewParamsWithPointsDTO
import space.nstart.pcp.pcp_types_lib.utils.UtcDateTimes
import java.time.LocalDateTime
@@ -55,8 +56,8 @@ class BallisticsService(webClientBuilderProvider: ObjectProvider<WebClient.Build
.get()
.uri("/api/satellites/{id}/rva?time_start={time_start}&time_stop={time_stop}",
id,
tn,
tk)
UtcDateTimes.format(tn),
UtcDateTimes.format(tk))
.retrieve()
.bodyToFlux<RadioVisibilityAreaDTO>()
.toIterable()
@@ -13,8 +13,9 @@ import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotStatus
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotsStatusChangedEvent
import space.nstart.pcp.pcp_types_lib.message.KafkaMessage
import space.nstart.pcp.pcp_types_lib.message.PcpKafkaEvent
import space.nstart.pcp.pcp_types_lib.utils.UtcDateTimes
import java.nio.charset.StandardCharsets
import java.time.LocalDateTime
import java.time.Clock
import java.util.UUID
@Component
@@ -26,7 +27,8 @@ class BookedSlotsEventPublisher(
kafkaTemplateProvider: ObjectProvider<KafkaTemplate<String, Any>>,
objectMapperProvider: ObjectProvider<ObjectMapper>,
@Value("\${app.kafka.topics.booked-slots:pcp.booked-slots}") private val topic: String,
@Value("\${spring.application.name:pcp-mission-planing-service}") private val applicationName: String
@Value("\${spring.application.name:pcp-mission-planing-service}") private val applicationName: String,
private val clock: Clock = Clock.systemUTC()
) {
private val logger = LoggerFactory.getLogger(this::class.java)
@@ -59,7 +61,7 @@ class BookedSlotsEventPublisher(
val event = BookedSlotsStatusChangedEvent(
bookedSlotIds = normalizedIds,
status = status,
occurredAt = LocalDateTime.now(),
occurredAt = UtcDateTimes.now(clock),
sourceService = applicationName,
missionId = missionId,
modeId = modeId,
@@ -10,6 +10,7 @@ import reactor.core.publisher.Mono
import space.nstart.pcp.pcp_types_lib.configuration.CustomErrorException
import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.SatelliteModeResponseDTO
import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.SatelliteModeSnapshotResponseDTO
import space.nstart.pcp.pcp_types_lib.utils.UtcDateTimes
import tools.jackson.databind.ObjectMapper
import java.time.LocalDateTime
@@ -70,8 +71,8 @@ class ComplexMissionService(webClientBuilderProvider: ObjectProvider<WebClient.B
.uri(
"/api/satellites/snapshots/{snapshotId}/modes?intervalStart={intervalStart}&intervalEnd={intervalEnd}",
snapshotId,
intervalStart,
intervalEnd
UtcDateTimes.format(intervalStart),
UtcDateTimes.format(intervalEnd)
)
.retrieve()
.onStatus({ status -> status.isError }) { response ->
@@ -60,6 +60,8 @@ import space.nstart.pcp.pcp_types_lib.dto.ballistics.ObjViewRequestDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.PositionDTO
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotStatus
import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.SatelliteModeResponseDTO
import space.nstart.pcp.pcp_types_lib.utils.UtcDateTimes
import java.time.Clock
import java.time.Duration
import java.time.LocalDateTime
import java.util.UUID
@@ -81,6 +83,7 @@ class MissionPlaningService(
private val complexMissionService: ComplexMissionService,
private val satelliteCatalogClient: SatelliteCatalogClient,
private val satelliteMissionTypeFactory: SatelliteMissionTypeFactory,
private val clock: Clock = Clock.systemUTC(),
private val logger: Logger = LoggerFactory.getLogger(MissionPlaningService::class.java)
) {
@@ -432,7 +435,7 @@ class MissionPlaningService(
overrideIntervalEnd: LocalDateTime? = null,
comPlanSnapshotId: Long? = null
): MissionSurveyCalculationResponseDTO {
val startedAt = LocalDateTime.now()
val startedAt = UtcDateTimes.now(clock)
logger.info(
"Расчет плана съемки stage 5 по persisted snapshot этапа 4 для миссии {}: requestedComPlanSnapshotId={}",
missionId,
@@ -520,7 +523,7 @@ class MissionPlaningService(
)
if (survs.isEmpty()) {
val finishedAt = LocalDateTime.now()
val finishedAt = UtcDateTimes.now(clock)
return MissionSurveyCalculationResponseDTO(
missionId = missionId,
completed = true,
@@ -565,7 +568,7 @@ class MissionPlaningService(
modeBookings.size
)
val finishedAt = LocalDateTime.now()
val finishedAt = UtcDateTimes.now(clock)
return MissionSurveyCalculationResponseDTO(
missionId = missionId,
completed = true,