diff --git a/changeIpInCurrentFolder.sh b/changeIpInCurrentFolder.sh new file mode 100755 index 0000000..68bcff2 --- /dev/null +++ b/changeIpInCurrentFolder.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + echo "Example: $0 192.168.60.201 192.168.60.201" + exit 1 +fi + +OLD_IP="$1" +NEW_IP="$2" + +is_valid_ip() { + local ip="$1" + + [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1 + + IFS='.' read -r a b c d <<< "$ip" + + for part in "$a" "$b" "$c" "$d"; do + (( part >= 0 && part <= 255 )) || return 1 + done +} + +if ! is_valid_ip "$OLD_IP"; then + echo "Invalid old IP: $OLD_IP" + exit 1 +fi + +if ! is_valid_ip "$NEW_IP"; then + echo "Invalid new IP: $NEW_IP" + exit 1 +fi + +export OLD_IP +export NEW_IP + +changed_files=0 +skipped_files=0 + +while IFS= read -r -d '' file; do + # Пропускаем бинарные файлы + if ! grep -Iq . "$file"; then + skipped_files=$((skipped_files + 1)) + continue + fi + + if perl -0ne ' + BEGIN { $old = quotemeta($ENV{"OLD_IP"}); } + exit 0 if /(? $NEW_IP" +echo "Files updated: $changed_files" +echo "Files skipped: $skipped_files" diff --git a/config-repo/application-dev.yaml b/config-repo/application-dev.yaml index c0ba214..4e14ccd 100644 --- a/config-repo/application-dev.yaml +++ b/config-repo/application-dev.yaml @@ -1,16 +1,16 @@ # TODO before merge request: вернуть старые адреса окружения. -# pcp.infra.postgres.host: 192.168.1.8 +# pcp.infra.postgres.host: 192.168.60.201 pcp: infra: postgres: - host: 192.168.1.8 + host: 192.168.60.201 port: 35400 kafka: - host: 192.168.1.8 + host: 192.168.60.201 port: 19092 network: - host: 192.168.1.8 + host: 192.168.60.201 ports: config: 8888 diff --git a/create_pcp_databases.sh b/create_pcp_databases.sh index 3e1314e..0cc247a 100755 --- a/create_pcp_databases.sh +++ b/create_pcp_databases.sh @@ -3,7 +3,7 @@ set -euo pipefail # PostgreSQL connection settings. Override via env if needed: # PGHOST=... PGPORT=... PGUSER=... PGPASSWORD=... ./create_pcp_databases.sh -PGHOST="${PGHOST:-192.168.1.8}" +PGHOST="${PGHOST:-192.168.60.201}" PGPORT="${PGPORT:-5432}" PGUSER="${PGUSER:-postgres}" PGPASSWORD="${PGPASSWORD:-password}" diff --git a/docs/standards/CHECKLIST.md b/docs/standards/CHECKLIST.md index 4dff708..c5461a4 100644 --- a/docs/standards/CHECKLIST.md +++ b/docs/standards/CHECKLIST.md @@ -21,7 +21,7 @@ - существующие публичные контракты не сломаны без явного запроса; - добавлены или обновлены релевантные тесты; - не внесено несвязанных правок; -- время на API — naive `LocalDateTime` без зоны; backend штампует `now` через `LocalDateTime.now(ZoneOffset.UTC)`, фронт парсит/форматирует через `utils/utcTime` без `new Date("<строка>")`; +- время на API — naive `LocalDateTime` без зоны; backend штампует `now` через `LocalDateTime.now()`, фронт парсит/форматирует через `utils/utcTime` без `new Date("<строка>")`; - egress фронта к бэку — naive ISO (`YYYY-MM-DDTHH:mm:ss`, без Z); - validation выполнен по правилам `AGENTS.md`, либо пропуски явно объяснены. diff --git a/docs/tasks/TASK_routes-drops-carryover.md b/docs/tasks/TASK_routes-drops-carryover.md new file mode 100644 index 0000000..f2ff451 --- /dev/null +++ b/docs/tasks/TASK_routes-drops-carryover.md @@ -0,0 +1,30 @@ +# Следующая задача: маршруты, сбросы и перенос включений между планами + +> Статус: запланировано (дизайн ещё не начат). Это фиксация намерения, не финальный план. + +Следующий блок работ — три связанные темы вокруг содержимого плана (включений) и +их съёмочно-сбросовой обвязки: + +## 1. Построение маршрутов +Довести построение маршрутов наблюдения по плану. Сейчас маршруты порождаются в +потоке `createSatelliteMission` (BPMN), где `planId == missionId`; результат +ложится в БД mission-planing. Уточнить: когда и по какому триггеру строятся +маршруты для нового/перевыданного плана, и как они привязаны к включениям. + +## 2. Формирование сбросов +Формирование сбросов (`DropMode`) поверх съёмочных включений (`SurveyMode`): +расчёт окон сброса, привязка к ЗРВ/КПП, согласование времени сброса со временем +съёмки. Внутренние времена — naive `LocalDateTime` (см. сквозную модель без зон). + +## 3. Перенос включений из плана в план +При перевыдаче/версионировании плана переносить уже сформированные включения +(съёмки + сбросы) из предыдущего плана в новый — чтобы не терять набранное +содержимое цепочки. Определить, что переносится как есть, что пересчитывается, +и как это стыкуется с двумя осями версионирования (цепочка ТГУ + контент миссии). + +## Контекст / связанные места +- Маршруты и их сохранение: `createSatelliteMission`, `planId == missionId`. +- Сбросы/съёмки: `pcp-mission-planing-service` — `SurveyMode`/`DropMode`, + `MissionPlaningService`. +- Версионирование/перевыдача плана — две оси (цепочка ТГУ + контент миссии). +- Время — сквозной naive `LocalDateTime` без зоны (после отката UTC-слоя). diff --git a/docs/задачи для pcp-tgu-ops-ui.txt b/docs/задачи для pcp-tgu-ops-ui.txt new file mode 100644 index 0000000..a3498a0 --- /dev/null +++ b/docs/задачи для pcp-tgu-ops-ui.txt @@ -0,0 +1,13 @@ +1. Перевод сервиса станций на ordinis по примеру получения аппаратов в сервисе tgu +2. Ошибка при попытке принять план во вкладке планы +3. Происходит накопление целей съемки, этого делать не нужно, пусть будет просто перекрестие на карте +А на панели справа пусть будет написано опорная точка прицеливания и ее координаты +4. Дата время в формате 24 часов а не AM PM, во всем интерфейсе. + + + +5. Добавить маску важности, чтобы можно было легко ввести 0.1 или 0.3 +6. При нажатии на включение нужно центрировать экран на него и подсвечивать выбор, будто кликнули по самому объекту на карте +7. Сбросы нужно отобрадать на картооснове как толстую яркую линию на трассе, время начала конца линии - время начала конца сброса +8. При нажатии на ЗРВ в окне Планы нужно справа отображать информацию по этим ЗРВ и если их несколько то по нескольких по примеру завок на вкладке Карта +10. Проблема того, что в одном и том же месте есть план Rejected и план WAIting_decision (скриншот сохранен) diff --git a/libs/pcp-types-lib/src/main/kotlin/space/nstart/pcp/pcp_types_lib/message/KafkaMessage.kt b/libs/pcp-types-lib/src/main/kotlin/space/nstart/pcp/pcp_types_lib/message/KafkaMessage.kt index d2349a2..0e55531 100644 --- a/libs/pcp-types-lib/src/main/kotlin/space/nstart/pcp/pcp_types_lib/message/KafkaMessage.kt +++ b/libs/pcp-types-lib/src/main/kotlin/space/nstart/pcp/pcp_types_lib/message/KafkaMessage.kt @@ -2,8 +2,9 @@ package space.nstart.pcp.pcp_types_lib.message import com.fasterxml.jackson.annotation.JsonFormat import com.fasterxml.jackson.annotation.JsonAlias +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import space.nstart.pcp.pcp_types_lib.utils.json.LocalDateTimeTimeZoneSerializer import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.* @@ -19,10 +20,9 @@ class KafkaMessage ( val id = UUID.randomUUID().toString() var source = "Example" - // Время конверта — naive LocalDateTime, штампуется по настенным часам UTC (now(ZoneOffset.UTC)), - // сериализуется как ISO без зоны. - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") - val time: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS[xxx]") + @JsonSerialize(using = LocalDateTimeTimeZoneSerializer::class) + val time: LocalDateTime = LocalDateTime.now() val dataContentType = "application/json" val specVersion = "1.0" diff --git a/libs/pcp-types-lib/src/main/kotlin/space/nstart/pcp/pcp_types_lib/utils/json/LocalDateTimeTimeZoneSerializer.kt b/libs/pcp-types-lib/src/main/kotlin/space/nstart/pcp/pcp_types_lib/utils/json/LocalDateTimeTimeZoneSerializer.kt new file mode 100644 index 0000000..f8a236e --- /dev/null +++ b/libs/pcp-types-lib/src/main/kotlin/space/nstart/pcp/pcp_types_lib/utils/json/LocalDateTimeTimeZoneSerializer.kt @@ -0,0 +1,22 @@ +package space.nstart.pcp.pcp_types_lib.utils.json + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.databind.JsonSerializer +import com.fasterxml.jackson.databind.SerializerProvider +import java.time.LocalDateTime +import java.time.ZoneId +import java.time.format.DateTimeFormatter + +class LocalDateTimeTimeZoneSerializer: JsonSerializer() { + + companion object { + val fmt: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx") + } + + override fun serialize(p0: LocalDateTime?, p1: JsonGenerator, p2: SerializerProvider) { + + //todo: проверить корректность зоны по нормальным правилам +// p1.writeString(p0?.atZone(ZoneId.of("Europe/Moscow"))?.format(fmt)) + p1.writeString(p0?.atZone(ZoneId.systemDefault())?.format(fmt)) + } +} diff --git a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/AscNodeEntity.kt b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/AscNodeEntity.kt index 74b021a..a7673b2 100644 --- a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/AscNodeEntity.kt +++ b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/AscNodeEntity.kt @@ -13,7 +13,6 @@ import jakarta.persistence.Table import space.nstart.pcp.pcp_types_lib.dto.ballistics.AscNodeDTO import space.nstart.pcp.pcp_types_lib.dto.ballistics.KeplersDTO import java.time.LocalDateTime -import java.time.ZoneOffset import kotlin.math.PI @@ -27,7 +26,7 @@ class AscNodeEntity( @Column(nullable = false) val satelliteId : Long = 0, @Column(name = "t", nullable = false) - val time : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val time : LocalDateTime = LocalDateTime.now(), @Column(nullable = false) val revolution : Long = 0, val longitude : Double = 0.0, diff --git a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/EarthCellViewsEntity.kt b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/EarthCellViewsEntity.kt index a2efa41..0e84c33 100644 --- a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/EarthCellViewsEntity.kt +++ b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/EarthCellViewsEntity.kt @@ -10,7 +10,6 @@ import jakarta.persistence.Table import space.nstart.pcp.pcp_types_lib.dto.ballistics.RevolutionSign import space.nstart.pcp.pcp_types_lib.dto.ballistics.SquareViewParamDTO import java.time.LocalDateTime -import java.time.ZoneOffset import kotlin.math.PI @Entity @@ -27,13 +26,13 @@ class EarthCellViewsEntity( @Column(name = "rev_begin", nullable = false) val revolutionBegin : Long = 0, @Column(nullable = false) - val timeBegin : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val timeBegin : LocalDateTime = LocalDateTime.now(), @Column(nullable = false) val revSignBegin : Int = 0, @Column(name = "rev_end", nullable = false) val revolutionEnd: Long = 0, @Column(nullable = false) - val timeEnd : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val timeEnd : LocalDateTime = LocalDateTime.now(), @Column(nullable = false) val revSignEnd : Int = 0, @Column(name = "roll_min") diff --git a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/EarthCoverageEntity.kt b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/EarthCoverageEntity.kt index e7d9cf7..2a924d5 100644 --- a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/EarthCoverageEntity.kt +++ b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/EarthCoverageEntity.kt @@ -9,7 +9,6 @@ import jakarta.persistence.GenerationType import jakarta.persistence.Id import jakarta.persistence.Table import java.time.LocalDateTime -import java.time.ZoneOffset @Entity @Table(name = "earth_coverage") @@ -23,9 +22,9 @@ class EarthCoverageEntity( @Column(nullable = false) val cellNumber : Long = 0, @Column(nullable = false) - val tStart : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val tStart : LocalDateTime = LocalDateTime.now(), @Column(nullable = false) - val tStop : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val tStop : LocalDateTime = LocalDateTime.now(), ) { constructor(fl : FleghtLineSector, sector : Int, sat : Long) : this( null, diff --git a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/FlightLineEntity.kt b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/FlightLineEntity.kt index d9fbd15..7d72c1e 100644 --- a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/FlightLineEntity.kt +++ b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/FlightLineEntity.kt @@ -6,7 +6,6 @@ import jakarta.persistence.* import space.nstart.pcp.pcp_types_lib.dto.ballistics.FlightLineDTO import space.nstart.pcp.pcp_types_lib.dto.ballistics.RevolutionSign import java.time.LocalDateTime -import java.time.ZoneOffset import kotlin.math.PI @@ -20,7 +19,7 @@ class FlightLineEntity( @Column(nullable = false) val satelliteId : Long = 0, @Column(name = "t", nullable = false) - val time : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val time : LocalDateTime = LocalDateTime.now(), @Column(nullable = false) val revolution : Long = 0, @Column(nullable = false) diff --git a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/PDCMEntity.kt b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/PDCMEntity.kt index 0da1e4c..afe03da 100644 --- a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/PDCMEntity.kt +++ b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/PDCMEntity.kt @@ -7,7 +7,6 @@ import ballistics.utils.toDateTime import jakarta.persistence.* import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO import java.time.LocalDateTime -import java.time.ZoneOffset @Entity @Table(name = "pdcm") @@ -19,7 +18,7 @@ class PDCMEntity ( @Column(nullable = false) val satelliteId : Long = 0, @Column(name = "t", nullable = false) - val time : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val time : LocalDateTime = LocalDateTime.now(), @Column(nullable = false) val revolution : Long = 0, val x: Double = 0.0, diff --git a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/SatelliteInitialConditionEntity.kt b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/SatelliteInitialConditionEntity.kt index 916e2b8..044f7de 100644 --- a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/SatelliteInitialConditionEntity.kt +++ b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/entity/SatelliteInitialConditionEntity.kt @@ -13,7 +13,6 @@ import space.nstart.pcp.pcp_types_lib.dto.ballistics.MovementModel import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO import java.time.LocalDateTime -import java.time.ZoneOffset @Entity @Table(name = "satellite_initial_conditions") @@ -28,7 +27,7 @@ class SatelliteInitialConditionEntity( @Column(name = "movement_model", nullable = false) val movementModel: MovementModel = MovementModel.FOTO, @Column(name = "orb_time", nullable = false) - val orbTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val orbTime: LocalDateTime = LocalDateTime.now(), @Column(name = "orb_revolution", nullable = false) val orbRevolution: Long = 0, @Column(nullable = false) @@ -48,7 +47,7 @@ class SatelliteInitialConditionEntity( @Column(nullable = false) val f81: Double = 147.8, @Column(name = "received_at", nullable = false) - val receivedAt: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val receivedAt: LocalDateTime = LocalDateTime.now(), @Column(name = "calculated_at") var calculatedAt: LocalDateTime? = null, @Column(name = "last_calculated", nullable = false) @@ -69,7 +68,7 @@ class SatelliteInitialConditionEntity( f81 = request.ic.f81 ) - fun markLastCalculated(calculatedAt: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC)) { + fun markLastCalculated(calculatedAt: LocalDateTime = LocalDateTime.now()) { this.calculatedAt = calculatedAt this.lastCalculated = true } diff --git a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/service/SatelliteService.kt b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/service/SatelliteService.kt index 8e40d7e..74d027b 100644 --- a/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/service/SatelliteService.kt +++ b/services/pcp-ballistics-service/src/main/kotlin/space/nstart/pcp/pcp_request_service/service/SatelliteService.kt @@ -63,7 +63,6 @@ import space.nstart.pcp.pcp_types_lib.dto.ballistics.TLEDTO import space.nstart.pcp.pcp_types_lib.dto.ballistics.TargetPositionDTO import tools.jackson.databind.ObjectMapper import java.time.LocalDateTime -import java.time.ZoneOffset import kotlin.collections.forEach import kotlin.math.PI import kotlin.math.abs @@ -762,8 +761,8 @@ class SatelliteService { fun getOrbPoints(id : Long, tn : LocalDateTime?, tk : LocalDateTime?) = pdcmRepository.findBySatelliteIdAndTimeBetween( id, - tn?: LocalDateTime.now(ZoneOffset.UTC), - tk?: LocalDateTime.now(ZoneOffset.UTC).plusDays(1)) + tn?: LocalDateTime.now(), + tk?: LocalDateTime.now().plusDays(1)) .map { it.toDTO() } @@ -776,8 +775,8 @@ class SatelliteService { fun getFL(id : Long, tn : LocalDateTime?, tk : LocalDateTime?, step : Double?) = flightLineRepository.findBySatelliteIdAndTimeBetween(id, - tn?: LocalDateTime.now(ZoneOffset.UTC), - tk?: LocalDateTime.now(ZoneOffset.UTC).plusDays(1) + tn?: LocalDateTime.now(), + tk?: LocalDateTime.now().plusDays(1) ) .map { it.toDTO() } @@ -898,8 +897,8 @@ class SatelliteService { return ascNodeRepository.findBySatelliteIdAndTimeBetween( id, - tn ?: LocalDateTime.now(ZoneOffset.UTC), - tk ?: LocalDateTime.now(ZoneOffset.UTC).plusDays(1) + tn ?: LocalDateTime.now(), + tk ?: LocalDateTime.now().plusDays(1) ) .map { val keps = calculateKeplerParams( diff --git a/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/ComplexPlanRunEntity.kt b/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/ComplexPlanRunEntity.kt index a7b599b..874fb10 100644 --- a/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/ComplexPlanRunEntity.kt +++ b/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/ComplexPlanRunEntity.kt @@ -13,7 +13,6 @@ import jakarta.persistence.Index import jakarta.persistence.OneToMany import jakarta.persistence.Table import java.time.LocalDateTime -import java.time.ZoneOffset @Entity @Table( @@ -35,7 +34,7 @@ class ComplexPlanRunEntity( var status: ComplexPlanRunStatus = ComplexPlanRunStatus.CREATED, @Column(name = "created_at", nullable = false) - var createdAt: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var createdAt: LocalDateTime = LocalDateTime.now(), @Column(name = "started_at") var startedAt: LocalDateTime? = null, @@ -47,10 +46,10 @@ class ComplexPlanRunEntity( var durationMs: Long? = null, @Column(name = "interval_start", nullable = false) - var intervalStart: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var intervalStart: LocalDateTime = LocalDateTime.now(), @Column(name = "interval_end", nullable = false) - var intervalEnd: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var intervalEnd: LocalDateTime = LocalDateTime.now(), @Column(name = "requested_by") var requestedBy: String? = null, diff --git a/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/SatelliteModeEntity.kt b/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/SatelliteModeEntity.kt index b090920..1c519d5 100644 --- a/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/SatelliteModeEntity.kt +++ b/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/SatelliteModeEntity.kt @@ -15,7 +15,6 @@ import jakarta.persistence.ManyToOne import jakarta.persistence.Table import jakarta.persistence.Index import java.time.LocalDateTime -import java.time.ZoneOffset @Entity @Table( @@ -44,10 +43,10 @@ class SatelliteModeEntity( var type: SatelliteModeType = SatelliteModeType.SURVEY, @Column(name = "start_time", nullable = false) - var startTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var startTime: LocalDateTime = LocalDateTime.now(), @Column(name = "end_time", nullable = false) - var endTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var endTime: LocalDateTime = LocalDateTime.now(), @Column(name = "revolution", nullable = false) var revolution: Long = 0, diff --git a/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/SatelliteModeSnapshotEntity.kt b/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/SatelliteModeSnapshotEntity.kt index 1b3e037..4d44d0e 100644 --- a/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/SatelliteModeSnapshotEntity.kt +++ b/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/entity/SatelliteModeSnapshotEntity.kt @@ -13,7 +13,6 @@ import jakarta.persistence.ManyToOne import jakarta.persistence.OneToMany import jakarta.persistence.Table import java.time.LocalDateTime -import java.time.ZoneOffset @Entity @Table( @@ -35,13 +34,13 @@ class SatelliteModeSnapshotEntity( var satelliteId: Long = 0, @Column(name = "interval_start", nullable = false) - var intervalStart: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var intervalStart: LocalDateTime = LocalDateTime.now(), @Column(name = "interval_end", nullable = false) - var intervalEnd: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var intervalEnd: LocalDateTime = LocalDateTime.now(), @Column(name = "created_at", nullable = false) - var createdAt: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var createdAt: LocalDateTime = LocalDateTime.now(), @Column(name = "is_active", nullable = false) var isActive: Boolean = false, diff --git a/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/model/mode/SurveyMode.kt b/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/model/mode/SurveyMode.kt index 984f120..05fc0bf 100644 --- a/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/model/mode/SurveyMode.kt +++ b/services/pcp-complex-mission-service/src/main/kotlin/space/nstart/pcp/pcp_satellites_service/model/mode/SurveyMode.kt @@ -3,12 +3,11 @@ package space.nstart.pcp.pcp_satellites_service.model.mode import space.nstart.pcp.pcp_satellites_service.entity.SatelliteModeSource import space.nstart.pcp.pcp_types_lib.dto.satellite.modes.SurveyModeInfoDTO import java.time.LocalDateTime -import java.time.ZoneOffset class SurveyMode( val revolution : Long = 1, - val time : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), - val timeStop : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + val time : LocalDateTime = LocalDateTime.now(), + val timeStop : LocalDateTime = LocalDateTime.now(), val roll : Double = 0.0, val latitude : Double = 0.0, val longitude : Double = 0.0, diff --git a/services/pcp-complex-mission-service/src/test/kotlin/space/nstart/pcp/pcp_satellites_service/controller/ComplexPlanControllerTest.kt b/services/pcp-complex-mission-service/src/test/kotlin/space/nstart/pcp/pcp_satellites_service/controller/ComplexPlanControllerTest.kt index b1b9915..af48f91 100644 --- a/services/pcp-complex-mission-service/src/test/kotlin/space/nstart/pcp/pcp_satellites_service/controller/ComplexPlanControllerTest.kt +++ b/services/pcp-complex-mission-service/src/test/kotlin/space/nstart/pcp/pcp_satellites_service/controller/ComplexPlanControllerTest.kt @@ -17,7 +17,6 @@ import space.nstart.pcp.pcp_satellites_service.service.ComplexMissionService import space.nstart.pcp.pcp_satellites_service.service.ComplexPlanRunOrchestrationService import space.nstart.pcp.pcp_types_lib.dto.requests.ComplexPlanProcessRequestDTO import java.time.LocalDateTime -import java.time.ZoneOffset import kotlin.test.assertContains import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/apl/BasicPlanCalculator.kt b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/apl/BasicPlanCalculator.kt index 78f7bff..be20de9 100644 --- a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/apl/BasicPlanCalculator.kt +++ b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/apl/BasicPlanCalculator.kt @@ -48,7 +48,6 @@ import java.time.Duration import java.time.Instant import java.time.LocalDate import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID import java.util.concurrent.ExecutionException import java.util.concurrent.Executors @@ -842,7 +841,7 @@ class BasicPlanCalculator( val resultFilePath = if (request.saveResultToFile && status == ComplexPlanCalculationStatus.COMPLETED) { observationParametersDebugFileWriter.write( ObservationParametersDebugFileDTO( - createdAt = LocalDateTime.now(ZoneOffset.UTC), + createdAt = LocalDateTime.now(), requestId = request.requestId, satelliteIds = selectedSatelliteIds, missingSatelliteIds = missingSatelliteIds, diff --git a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/db/entity/DynamicPlanRouteEntity.kt b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/db/entity/DynamicPlanRouteEntity.kt index 4f496ed..259202f 100644 --- a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/db/entity/DynamicPlanRouteEntity.kt +++ b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/db/entity/DynamicPlanRouteEntity.kt @@ -10,7 +10,6 @@ import jakarta.persistence.JoinColumn import jakarta.persistence.ManyToOne import jakarta.persistence.Table import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID @Table(name = "dynamic_plan_route") @@ -32,10 +31,10 @@ class DynamicPlanRouteEntity( var satelliteId: Long = 0, @Column(name = "start_time", nullable = false) - var startTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var startTime: LocalDateTime = LocalDateTime.now(), @Column(name = "end_time", nullable = false) - var endTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var endTime: LocalDateTime = LocalDateTime.now(), @Column(name = "duration", nullable = false) var duration: Double = 0.0, diff --git a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/db/entity/DynamicPlanRunEntity.kt b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/db/entity/DynamicPlanRunEntity.kt index 6c1f32b..a307bdb 100644 --- a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/db/entity/DynamicPlanRunEntity.kt +++ b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/db/entity/DynamicPlanRunEntity.kt @@ -10,7 +10,6 @@ import space.nstart.pcp.complan.types.DynamicPlanCalculationMode import space.nstart.pcp.complan.types.DynamicPlanRevolutionMode import space.nstart.pcp.complan.types.DynamicPlanRunStatus import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID @Table(name = "dynamic_plan_run") @@ -48,7 +47,7 @@ class DynamicPlanRunEntity( var filterCoveredRoutes: Boolean = false, @Column(name = "created_at", nullable = false) - var createdAt: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC), + var createdAt: LocalDateTime = LocalDateTime.now(), @Column(name = "started_at") var startedAt: LocalDateTime? = null, diff --git a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/service/DynamicPlanRunService.kt b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/service/DynamicPlanRunService.kt index d528a51..3afa0da 100644 --- a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/service/DynamicPlanRunService.kt +++ b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/service/DynamicPlanRunService.kt @@ -25,7 +25,6 @@ import space.nstart.pcp.complan.types.DynamicPlanRunStatus import space.nstart.pcp.complan.types.IntervalItemDTO import space.nstart.pcp.complan.types.SurveyContour import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID import java.util.concurrent.ExecutorService import kotlin.math.roundToLong @@ -60,7 +59,7 @@ class DynamicPlanRunService( calculationMode = request.calculationMode, revolutionMode = request.revolutionMode, filterCoveredRoutes = request.filterCoveredRoutes, - createdAt = LocalDateTime.now(ZoneOffset.UTC) + createdAt = LocalDateTime.now() ) ) } ?: throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to create calculation run") @@ -136,7 +135,7 @@ class DynamicPlanRunService( return@execute 0 } - val finishedAt = LocalDateTime.now(ZoneOffset.UTC) + val finishedAt = LocalDateTime.now() runs.forEach { run -> run.status = DynamicPlanRunStatus.FAILED run.finishedAt = finishedAt @@ -172,7 +171,7 @@ class DynamicPlanRunService( transactionTemplate.execute { val run = runRepository.findById(runId).orElse(null) ?: return@execute null run.status = DynamicPlanRunStatus.RUNNING - run.startedAt = LocalDateTime.now(ZoneOffset.UTC) + run.startedAt = LocalDateTime.now() run.errorMessage = null runRepository.save(run) run.toRequest() @@ -183,7 +182,7 @@ class DynamicPlanRunService( val run = runRepository.findById(runId).orElseThrow() val result = output.result run.status = DynamicPlanRunStatus.COMPLETED - run.finishedAt = LocalDateTime.now(ZoneOffset.UTC) + run.finishedAt = LocalDateTime.now() run.durationMs = result.durationMs run.resultStatus = result.status.name run.routesCount = result.routesCount @@ -201,7 +200,7 @@ class DynamicPlanRunService( transactionTemplate.execute { val run = runRepository.findById(runId).orElseThrow() run.status = DynamicPlanRunStatus.FAILED - run.finishedAt = LocalDateTime.now(ZoneOffset.UTC) + run.finishedAt = LocalDateTime.now() run.errorMessage = error.message ?: error::class.java.simpleName runRepository.save(run) } diff --git a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/spacecraft/SpaceCraft.kt b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/spacecraft/SpaceCraft.kt index 72334fe..853aeec 100755 --- a/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/spacecraft/SpaceCraft.kt +++ b/services/pcp-dynamic-plan-service/src/main/kotlin/space/nstart/pcp/complan/spacecraft/SpaceCraft.kt @@ -6,7 +6,6 @@ import org.locationtech.jts.geom.LineString import space.nstart.pcp.pcp_types_lib.dto.ballistics.FlightLineDTO import space.nstart.pcp.pcp_types_lib.dto.ballistics.RevolutionSign import java.time.LocalDateTime -import java.time.ZoneOffset /** * Класс космического аппарата** @@ -18,9 +17,9 @@ class SpaceCraft ( val flightLine : MutableList = mutableListOf() /**Время начала планирования аппарата*/ - var timeStart: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC) + var timeStart: LocalDateTime = LocalDateTime.now() /**Время конца планирования аппарата*/ - var timeStop : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC) + var timeStop : LocalDateTime = LocalDateTime.now() /** * Создание линий полета восходящего и нисходящего витка * @param geomFactory фабрика геометрии diff --git a/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/controller/MissionCloneDTOs.kt b/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/controller/MissionCloneDTOs.kt index c86005f..ae22aaa 100644 --- a/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/controller/MissionCloneDTOs.kt +++ b/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/controller/MissionCloneDTOs.kt @@ -12,9 +12,9 @@ object CloneMode { data class MissionCloneRequest( /** [CloneMode.REPLACE] — полный клон; [CloneMode.FORK_FORWARD] — только включения, перекрывающиеся с окном. */ val mode: String, - /** Начало окна нового плана (UTC naive). Обязательно для fork-forward. */ + /** Начало окна нового плана (naive, локальное время). Обязательно для fork-forward. */ val windowStart: LocalDateTime? = null, - /** Конец окна нового плана (UTC naive). Обязательно для fork-forward. */ + /** Конец окна нового плана (naive, локальное время). Обязательно для fork-forward. */ val windowStop: LocalDateTime? = null ) @@ -24,8 +24,8 @@ data class MissionCloneResponse(val newMissionId: UUID) data class MissionBlankRequest( /** КА (= noradId). */ val satelliteId: Long, - /** Начало окна миссии (UTC naive). */ + /** Начало окна миссии (naive, локальное время). */ val missionStart: LocalDateTime, - /** Конец окна миссии (UTC naive). */ + /** Конец окна миссии (naive, локальное время). */ val missionStop: LocalDateTime ) diff --git a/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/BookedSlotsEventPublisher.kt b/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/BookedSlotsEventPublisher.kt index f144289..4587cc3 100644 --- a/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/BookedSlotsEventPublisher.kt +++ b/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/BookedSlotsEventPublisher.kt @@ -15,7 +15,6 @@ import space.nstart.pcp.pcp_types_lib.message.KafkaMessage import space.nstart.pcp.pcp_types_lib.message.PcpKafkaEvent import java.nio.charset.StandardCharsets import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID @Component @@ -60,7 +59,7 @@ class BookedSlotsEventPublisher( val event = BookedSlotsStatusChangedEvent( bookedSlotIds = normalizedIds, status = status, - occurredAt = LocalDateTime.now(ZoneOffset.UTC), + occurredAt = LocalDateTime.now(), sourceService = applicationName, missionId = missionId, modeId = modeId, diff --git a/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/MissionPlaningService.kt b/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/MissionPlaningService.kt index d48476a..607d63b 100644 --- a/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/MissionPlaningService.kt +++ b/services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/MissionPlaningService.kt @@ -62,7 +62,6 @@ import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotStatus import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.SatelliteModeResponseDTO import java.time.Duration import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID import kotlin.math.PI import kotlin.math.abs @@ -433,7 +432,7 @@ class MissionPlaningService( overrideIntervalEnd: LocalDateTime? = null, comPlanSnapshotId: Long? = null ): MissionSurveyCalculationResponseDTO { - val startedAt = LocalDateTime.now(ZoneOffset.UTC) + val startedAt = LocalDateTime.now() logger.info( "Расчет плана съемки stage 5 по persisted snapshot этапа 4 для миссии {}: requestedComPlanSnapshotId={}", missionId, @@ -521,7 +520,7 @@ class MissionPlaningService( ) if (survs.isEmpty()) { - val finishedAt = LocalDateTime.now(ZoneOffset.UTC) + val finishedAt = LocalDateTime.now() return MissionSurveyCalculationResponseDTO( missionId = missionId, completed = true, @@ -566,7 +565,7 @@ class MissionPlaningService( modeBookings.size ) - val finishedAt = LocalDateTime.now(ZoneOffset.UTC) + val finishedAt = LocalDateTime.now() return MissionSurveyCalculationResponseDTO( missionId = missionId, completed = true, diff --git a/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/GridRebuildService.kt b/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/GridRebuildService.kt index eee1af5..39d0438 100644 --- a/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/GridRebuildService.kt +++ b/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/GridRebuildService.kt @@ -8,7 +8,6 @@ import org.nstart.dep265.requestservice.repository.RequestRepository import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime -import java.time.ZoneOffset class GridRebuildAlreadyRunningException : RuntimeException("Grid rebuild is already running") @@ -41,7 +40,7 @@ class GridRebuildService( return GridRebuildResponseDto( cellsCount = earthCellRepository.count(), rebuiltRequestProjectionsCount = activeRequests.size.toLong(), - rebuiltAt = LocalDateTime.now(ZoneOffset.UTC), + rebuiltAt = LocalDateTime.now(), ) } diff --git a/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/OutboxPublisherService.kt b/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/OutboxPublisherService.kt index 55672f2..31627eb 100644 --- a/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/OutboxPublisherService.kt +++ b/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/OutboxPublisherService.kt @@ -12,7 +12,6 @@ import org.springframework.stereotype.Service import org.springframework.transaction.support.TransactionCallback import org.springframework.transaction.support.TransactionOperations import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.concurrent.ExecutionException @Service @@ -70,7 +69,7 @@ class OutboxPublisherService( .get() event.status = OutboxEventStatus.PUBLISHED - event.publishedAt = LocalDateTime.now(ZoneOffset.UTC) + event.publishedAt = LocalDateTime.now() event.errorMessage = null outboxEventRepository.save(event) diff --git a/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/RequestService.kt b/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/RequestService.kt index a59ead0..13d366e 100644 --- a/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/RequestService.kt +++ b/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/RequestService.kt @@ -39,7 +39,6 @@ import org.springframework.data.domain.Sort import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID class InvalidRequestListSortException(message: String) : IllegalArgumentException(message) @@ -65,7 +64,7 @@ class RequestService( "beginDateTime должен быть раньше endDateTime" } - val now = LocalDateTime.now(ZoneOffset.UTC) + val now = LocalDateTime.now() val normalizedGeometry = geometryService.parsePolygonalGeometry(request.geometry) val normalizedGeometryWkt = geometryService.toWkt(normalizedGeometry) val geometryArea = geometryService.area(normalizedGeometry) @@ -153,7 +152,7 @@ class RequestService( @Transactional fun deleteRequest(id: UUID): DeleteRequestResponseDto? { val request = requestRepository.findById(id).orElse(null) ?: return null - val deletedAt = request.deletedAt ?: LocalDateTime.now(ZoneOffset.UTC) + val deletedAt = request.deletedAt ?: LocalDateTime.now() request.status = RequestStatus.DELETED request.deletedAt = deletedAt request.updatedAt = deletedAt diff --git a/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/RouteMatchingService.kt b/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/RouteMatchingService.kt index fbe5676..0fb6ed7 100644 --- a/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/RouteMatchingService.kt +++ b/services/pcp-request-service/src/main/kotlin/org/nstart/dep265/requestservice/service/RouteMatchingService.kt @@ -15,7 +15,6 @@ import org.springframework.stereotype.Service import org.springframework.transaction.support.TransactionCallback import org.springframework.transaction.support.TransactionOperations import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID import kotlin.math.max import kotlin.math.min @@ -44,7 +43,7 @@ class RouteMatchingService( val routeId = route.routeId val routeRollRange = route.rollAngle - val matchedAt: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC) + val matchedAt: LocalDateTime = LocalDateTime.now() val routeGeometry = geometryService.parsePolygonalGeometry(route.geometry) val candidateRequestIds = requestRepository.findRequestIdsForRoute( diff --git a/services/pcp-request-service/src/test/kotlin/org/nstart/dep265/requestservice/service/RequestGridProjectionServiceTest.kt b/services/pcp-request-service/src/test/kotlin/org/nstart/dep265/requestservice/service/RequestGridProjectionServiceTest.kt index f4c68fe..1a9f7cc 100644 --- a/services/pcp-request-service/src/test/kotlin/org/nstart/dep265/requestservice/service/RequestGridProjectionServiceTest.kt +++ b/services/pcp-request-service/src/test/kotlin/org/nstart/dep265/requestservice/service/RequestGridProjectionServiceTest.kt @@ -13,7 +13,6 @@ import org.nstart.dep265.requestservice.repository.EarthCellRepository import org.nstart.dep265.requestservice.repository.RequestCellRepository import org.nstart.dep265.requestservice.repository.RequestRepository import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -113,14 +112,14 @@ class RequestGridProjectionServiceTest { geometryArea = 1.0, remainingArea = 1.0, importance = importance, - beginDateTime = LocalDateTime.now(ZoneOffset.UTC), - endDateTime = LocalDateTime.now(ZoneOffset.UTC).plusDays(1), + beginDateTime = LocalDateTime.now(), + endDateTime = LocalDateTime.now().plusDays(1), highPriorityTransmit = false, surveyType = RequestSurveyType.OPTICS, status = RequestStatus.ACTIVE, matchCount = 0, - createdAt = LocalDateTime.now(ZoneOffset.UTC), - updatedAt = LocalDateTime.now(ZoneOffset.UTC), + createdAt = LocalDateTime.now(), + updatedAt = LocalDateTime.now(), ) ) diff --git a/services/pcp-request-service/src/test/kotlin/org/nstart/dep265/requestservice/service/RouteMatchingServiceTest.kt b/services/pcp-request-service/src/test/kotlin/org/nstart/dep265/requestservice/service/RouteMatchingServiceTest.kt index 5aff657..6af3400 100644 --- a/services/pcp-request-service/src/test/kotlin/org/nstart/dep265/requestservice/service/RouteMatchingServiceTest.kt +++ b/services/pcp-request-service/src/test/kotlin/org/nstart/dep265/requestservice/service/RouteMatchingServiceTest.kt @@ -29,7 +29,6 @@ import org.springframework.transaction.support.SimpleTransactionStatus import org.springframework.transaction.support.TransactionCallback import org.springframework.transaction.support.TransactionOperations import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.Optional import java.util.UUID @@ -48,7 +47,7 @@ class RouteMatchingServiceTest { geometryService = geometryService, ) - val intervalBegin = LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5).withNano(0) + val intervalBegin = LocalDateTime.now().minusMinutes(5).withNano(0) val intervalEnd = intervalBegin.plusHours(1) val request = request( beginDateTime = intervalBegin, @@ -97,7 +96,7 @@ class RouteMatchingServiceTest { geometryService = geometryService, ) - val intervalBegin = LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5).withNano(0) + val intervalBegin = LocalDateTime.now().minusMinutes(5).withNano(0) val intervalEnd = intervalBegin.plusHours(1) val originalRemainingGeometry = "POLYGON((1 1, 2 1, 2 2, 1 2, 1 1))" val request = request( @@ -147,7 +146,7 @@ class RouteMatchingServiceTest { geometryService = geometryService, ) - val intervalBegin = LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5).withNano(0) + val intervalBegin = LocalDateTime.now().minusMinutes(5).withNano(0) val request = request( beginDateTime = intervalBegin, endDateTime = intervalBegin.plusHours(1), @@ -183,7 +182,7 @@ class RouteMatchingServiceTest { geometryService = geometryService, ) - val intervalBegin = LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5).withNano(0) + val intervalBegin = LocalDateTime.now().minusMinutes(5).withNano(0) val request = request( beginDateTime = intervalBegin, endDateTime = intervalBegin.plusHours(1), @@ -231,7 +230,7 @@ class RouteMatchingServiceTest { geometryService = geometryService, ) - val intervalBegin = LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5).withNano(0) + val intervalBegin = LocalDateTime.now().minusMinutes(5).withNano(0) val request = request( beginDateTime = intervalBegin, endDateTime = intervalBegin.plusHours(1), @@ -269,7 +268,7 @@ class RouteMatchingServiceTest { geometryService = geometryService, ) - val intervalBegin = LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5).withNano(0) + val intervalBegin = LocalDateTime.now().minusMinutes(5).withNano(0) val request = request( beginDateTime = intervalBegin, endDateTime = intervalBegin.plusHours(1), diff --git a/services/pcp-route-processing-service/src/main/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportIngestionService.kt b/services/pcp-route-processing-service/src/main/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportIngestionService.kt index 6a0c768..fe4d09e 100644 --- a/services/pcp-route-processing-service/src/main/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportIngestionService.kt +++ b/services/pcp-route-processing-service/src/main/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportIngestionService.kt @@ -17,7 +17,6 @@ import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper as JpaJsonObjectMapper import tools.jackson.databind.ObjectMapper import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID /** @@ -39,7 +38,7 @@ class RoutePassportIngestionService( rawPayload: String, sourceRecord: RoutePassportSourceRecordMetadata, ) { - val now = LocalDateTime.now(ZoneOffset.UTC) + val now = LocalDateTime.now() val routePassportDto = parsedMessage.routePassportDto val existingRoutePassport = routePassportRepository.findById(routePassportDto.routeId) val routeCreated = existingRoutePassport.isEmpty diff --git a/services/pcp-route-processing-service/src/main/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportOutboxService.kt b/services/pcp-route-processing-service/src/main/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportOutboxService.kt index ae0a3e9..052c820 100644 --- a/services/pcp-route-processing-service/src/main/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportOutboxService.kt +++ b/services/pcp-route-processing-service/src/main/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportOutboxService.kt @@ -9,7 +9,6 @@ import space.nstart.pcp.routepassportconsumer.entity.RoutePassportOutboxStatus import space.nstart.pcp.routepassportconsumer.repository.RoutePassportOutboxRepository import java.time.Duration import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.UUID /** @@ -33,7 +32,7 @@ class RoutePassportOutboxService( return emptyList() } - val now = LocalDateTime.now(ZoneOffset.UTC) + val now = LocalDateTime.now() val lockedUntil = now.plus(Duration.ofMillis(outboxProperties.lockTimeoutMs)) val claimedRows = routePassportOutboxRepository.findDueForUpdateSkipLocked(outboxProperties.batchSize) @@ -71,7 +70,7 @@ class RoutePassportOutboxService( */ @Transactional fun markPublished(outboxId: UUID) { - val now = LocalDateTime.now(ZoneOffset.UTC) + val now = LocalDateTime.now() val outbox = findOutbox(outboxId) outbox.status = RoutePassportOutboxStatus.PUBLISHED @@ -100,7 +99,7 @@ class RoutePassportOutboxService( */ @Transactional fun markRetryOrFailed(outboxId: UUID, exception: Exception) { - val now = LocalDateTime.now(ZoneOffset.UTC) + val now = LocalDateTime.now() val outbox = findOutbox(outboxId) outbox.attempts += 1 diff --git a/services/pcp-route-processing-service/src/main/resources/test-passport-message.json b/services/pcp-route-processing-service/src/main/resources/test-passport-message.json index c0d5ef7..fc0da12 100644 --- a/services/pcp-route-processing-service/src/main/resources/test-passport-message.json +++ b/services/pcp-route-processing-service/src/main/resources/test-passport-message.json @@ -98,7 +98,7 @@ ], "assets": { "schema-calibration-vh": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/calibration-s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=26988c6a3490f71382ae9e61ff0d7b59aca32ec652993a785d24e8dd81e70939", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/calibration-s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=26988c6a3490f71382ae9e61ff0d7b59aca32ec652993a785d24e8dd81e70939", "title": "xml", "description": null, "type": "application/xml", @@ -107,7 +107,7 @@ ] }, "schema-calibration-vv": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/calibration-s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=edd6957a0404ead07e7a31d0759db26b3a6ad33394247c177dc41a7abf5972d0", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/calibration-s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=edd6957a0404ead07e7a31d0759db26b3a6ad33394247c177dc41a7abf5972d0", "title": "xml", "description": null, "type": "application/xml", @@ -116,7 +116,7 @@ ] }, "schema-noise-vh": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/noise-s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=3efe46114ed6dfeac898963510d3ba9c8b537c803b1fa69a5a03d5b462a1665c", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/noise-s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=3efe46114ed6dfeac898963510d3ba9c8b537c803b1fa69a5a03d5b462a1665c", "title": "xml", "description": null, "type": "application/xml", @@ -125,7 +125,7 @@ ] }, "schema-noise-vv": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/noise-s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=0ca91479ba4132dbf13c2637f97567eb29ee9ca818009eaf501072995fe784ca", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/noise-s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=0ca91479ba4132dbf13c2637f97567eb29ee9ca818009eaf501072995fe784ca", "title": "xml", "description": null, "type": "application/xml", @@ -134,7 +134,7 @@ ] }, "schema-product-vh": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=39817f0b7610c0b20a23d0fae24e7183f0d3719ba6ab2f315c320c9c6530274f", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=39817f0b7610c0b20a23d0fae24e7183f0d3719ba6ab2f315c320c9c6530274f", "title": "xml", "description": null, "type": "application/xml", @@ -143,7 +143,7 @@ ] }, "schema-product-vv": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=85d28bc2bb94724b4db7df84121d4252b423fa429204e4b25e06b9d725f3aeee", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=85d28bc2bb94724b4db7df84121d4252b423fa429204e4b25e06b9d725f3aeee", "title": "xml", "description": null, "type": "application/xml", @@ -152,7 +152,7 @@ ] }, "safe-manifest": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/manifest.safe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=dbb22d57d031a412e2b46273edf32cfcb7fbdae1fa1fcc74bdcaa39a5e086f53", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/manifest.safe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=dbb22d57d031a412e2b46273edf32cfcb7fbdae1fa1fcc74bdcaa39a5e086f53", "title": "safe", "description": null, "type": "application/xml", @@ -161,7 +161,7 @@ ] }, "vh": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002_cog.tif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120824Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=dbecc9e04e976751e855f53e9a9a8db5d6365a30ac7ec116f31b0936ee375648", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002_cog.tif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120824Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=dbecc9e04e976751e855f53e9a9a8db5d6365a30ac7ec116f31b0936ee375648", "title": "tif", "description": null, "type": "image/tiff; application=geotiff; profile=cloud-optimized", @@ -170,7 +170,7 @@ ] }, "vv": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001_cog.tif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=34cf1e5f5174b7cb5ca5d173ff699923819d5df28486436d972efa59ac9b1ddb", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001_cog.tif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=34cf1e5f5174b7cb5ca5d173ff699923819d5df28486436d972efa59ac9b1ddb", "title": "tif", "description": null, "type": "image/tiff; application=geotiff; profile=cloud-optimized", @@ -179,7 +179,7 @@ ] }, "kml": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/map-overlay.kml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=92f63b9f463041c4ed87b3cb508ba8c57fd2db8ea2d22026087ba57d2ef88f54", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/map-overlay.kml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=92f63b9f463041c4ed87b3cb508ba8c57fd2db8ea2d22026087ba57d2ef88f54", "title": "kml", "description": null, "type": "application/kml", @@ -188,7 +188,7 @@ ] }, "thumbnail": { - "href": "http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/quick-look.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=19bebb1e446add1d6e0898b4329d2a3e016f59087719ce2b51dff5c487835cb0", + "href": "http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/quick-look.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=19bebb1e446add1d6e0898b4329d2a3e016f59087719ce2b51dff5c487835cb0", "title": "png", "description": null, "type": "image/png", diff --git a/services/pcp-route-processing-service/src/test/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportIngestionServiceTest.kt b/services/pcp-route-processing-service/src/test/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportIngestionServiceTest.kt index e9db81c..2841ebc 100644 --- a/services/pcp-route-processing-service/src/test/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportIngestionServiceTest.kt +++ b/services/pcp-route-processing-service/src/test/kotlin/space/nstart/pcp/routepassportconsumer/service/RoutePassportIngestionServiceTest.kt @@ -27,7 +27,6 @@ import tools.jackson.databind.json.JsonMapper import tools.jackson.module.kotlin.KotlinModule import java.math.BigDecimal import java.time.LocalDateTime -import java.time.ZoneOffset import java.util.Optional import java.util.UUID @@ -220,9 +219,9 @@ class RoutePassportIngestionServiceTest { status = RoutePassportOutboxStatus.PENDING, attempts = 0, maxAttempts = 10, - nextAttemptAt = LocalDateTime.now(ZoneOffset.UTC), - createdAt = LocalDateTime.now(ZoneOffset.UTC), - updatedAt = LocalDateTime.now(ZoneOffset.UTC), + nextAttemptAt = LocalDateTime.now(), + createdAt = LocalDateTime.now(), + updatedAt = LocalDateTime.now(), ) private fun fixture(): IngestionFixture { diff --git a/services/pcp-route-processing-service/src/test/resources/passport_example.json b/services/pcp-route-processing-service/src/test/resources/passport_example.json index 0f26d6c..9357750 100644 --- a/services/pcp-route-processing-service/src/test/resources/passport_example.json +++ b/services/pcp-route-processing-service/src/test/resources/passport_example.json @@ -1 +1 @@ -{"type":"Feature","stac_version":"1.0.0","stac_extensions":null,"id":"S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE","collection":"S1A-GRDH","geometry":"POLYGON((67.675827 38.114815, 64.779434 38.514816, 65.094017 40.015545, 68.05294 39.616795, 67.675827 38.114815))","bbox":[64.779434,40.015545,68.05294,38.114815],"properties":{"datetime":"2026-03-31T12:08:30.570573Z","created":null,"updated":"2026-03-31T12:08:30.610660Z","platform":"sentinel-1a","instruments":null,"processing:level":"GRD","route:orbit_number":"59796","missionId":"S1A","sat:orbit_state":"Descending","polarisation":["VH","VV"],"rollAngle":[30.07864486915724,30.09378936608302],"visirAngle":[30.63331560676386,46.07086702096005],"intervalBegin":"2025-06-25T01:38:54.481190","intervalEnd":"2025-06-25T01:39:19.479675","resolutionRange":"1.000000e+01","resolutionAzimuth":"1.000000e+01"},"links":[{"rel":"self","type":"application/geo+json","href":"http://192.168.1.8:8085/collections/S1A-GRDH/items/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE"},{"rel":"parent","type":"application/json","href":"http://192.168.1.8:8085/collections/S1A-GRDH"},{"rel":"collection","type":"application/json","href":"http://192.168.1.8:8085/collections/S1A-GRDH"},{"rel":"root","type":"application/json","href":"http://192.168.1.8:8085/"}],"assets":{"schema-calibration-vh":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/calibration-s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=26988c6a3490f71382ae9e61ff0d7b59aca32ec652993a785d24e8dd81e70939","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-calibration-vv":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/calibration-s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=edd6957a0404ead07e7a31d0759db26b3a6ad33394247c177dc41a7abf5972d0","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-noise-vh":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/noise-s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=3efe46114ed6dfeac898963510d3ba9c8b537c803b1fa69a5a03d5b462a1665c","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-noise-vv":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/noise-s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=0ca91479ba4132dbf13c2637f97567eb29ee9ca818009eaf501072995fe784ca","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-product-vh":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=39817f0b7610c0b20a23d0fae24e7183f0d3719ba6ab2f315c320c9c6530274f","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-product-vv":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=85d28bc2bb94724b4db7df84121d4252b423fa429204e4b25e06b9d725f3aeee","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"safe-manifest":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/manifest.safe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=dbb22d57d031a412e2b46273edf32cfcb7fbdae1fa1fcc74bdcaa39a5e086f53","type":"application/xml","title":"safe","description":null,"roles":["metadata"]},"vh":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002_cog.tif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120824Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=dbecc9e04e976751e855f53e9a9a8db5d6365a30ac7ec116f31b0936ee375648","type":"image/tiff; application=geotiff; profile=cloud-optimized","title":"tif","description":null,"roles":["visual"]},"vv":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001_cog.tif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=34cf1e5f5174b7cb5ca5d173ff699923819d5df28486436d972efa59ac9b1ddb","type":"image/tiff; application=geotiff; profile=cloud-optimized","title":"tif","description":null,"roles":["visual"]},"kml":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/map-overlay.kml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=92f63b9f463041c4ed87b3cb508ba8c57fd2db8ea2d22026087ba57d2ef88f54","type":"application/kml","title":"kml","description":null,"roles":["metadata"]},"thumbnail":{"href":"http://192.168.1.8:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/quick-look.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=19bebb1e446add1d6e0898b4329d2a3e016f59087719ce2b51dff5c487835cb0","type":"image/png","title":"png","description":null,"roles":["thumbnail","overview"]}}} +{"type":"Feature","stac_version":"1.0.0","stac_extensions":null,"id":"S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE","collection":"S1A-GRDH","geometry":"POLYGON((67.675827 38.114815, 64.779434 38.514816, 65.094017 40.015545, 68.05294 39.616795, 67.675827 38.114815))","bbox":[64.779434,40.015545,68.05294,38.114815],"properties":{"datetime":"2026-03-31T12:08:30.570573Z","created":null,"updated":"2026-03-31T12:08:30.610660Z","platform":"sentinel-1a","instruments":null,"processing:level":"GRD","route:orbit_number":"59796","missionId":"S1A","sat:orbit_state":"Descending","polarisation":["VH","VV"],"rollAngle":[30.07864486915724,30.09378936608302],"visirAngle":[30.63331560676386,46.07086702096005],"intervalBegin":"2025-06-25T01:38:54.481190","intervalEnd":"2025-06-25T01:39:19.479675","resolutionRange":"1.000000e+01","resolutionAzimuth":"1.000000e+01"},"links":[{"rel":"self","type":"application/geo+json","href":"http://192.168.60.201:8085/collections/S1A-GRDH/items/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE"},{"rel":"parent","type":"application/json","href":"http://192.168.60.201:8085/collections/S1A-GRDH"},{"rel":"collection","type":"application/json","href":"http://192.168.60.201:8085/collections/S1A-GRDH"},{"rel":"root","type":"application/json","href":"http://192.168.60.201:8085/"}],"assets":{"schema-calibration-vh":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/calibration-s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=26988c6a3490f71382ae9e61ff0d7b59aca32ec652993a785d24e8dd81e70939","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-calibration-vv":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/calibration-s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=edd6957a0404ead07e7a31d0759db26b3a6ad33394247c177dc41a7abf5972d0","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-noise-vh":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/noise-s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=3efe46114ed6dfeac898963510d3ba9c8b537c803b1fa69a5a03d5b462a1665c","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-noise-vv":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/noise-s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=0ca91479ba4132dbf13c2637f97567eb29ee9ca818009eaf501072995fe784ca","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-product-vh":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=39817f0b7610c0b20a23d0fae24e7183f0d3719ba6ab2f315c320c9c6530274f","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"schema-product-vv":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=85d28bc2bb94724b4db7df84121d4252b423fa429204e4b25e06b9d725f3aeee","type":"application/xml","title":"xml","description":null,"roles":["metadata"]},"safe-manifest":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/manifest.safe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120819Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=dbb22d57d031a412e2b46273edf32cfcb7fbdae1fa1fcc74bdcaa39a5e086f53","type":"application/xml","title":"safe","description":null,"roles":["metadata"]},"vh":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vh-20250625t013854-20250625t013919-059796-076d15-002_cog.tif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120824Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=dbecc9e04e976751e855f53e9a9a8db5d6365a30ac7ec116f31b0936ee375648","type":"image/tiff; application=geotiff; profile=cloud-optimized","title":"tif","description":null,"roles":["visual"]},"vv":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/s1a-iw-grd-vv-20250625t013854-20250625t013919-059796-076d15-001_cog.tif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=34cf1e5f5174b7cb5ca5d173ff699923819d5df28486436d972efa59ac9b1ddb","type":"image/tiff; application=geotiff; profile=cloud-optimized","title":"tif","description":null,"roles":["visual"]},"kml":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/map-overlay.kml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=92f63b9f463041c4ed87b3cb508ba8c57fd2db8ea2d22026087ba57d2ef88f54","type":"application/kml","title":"kml","description":null,"roles":["metadata"]},"thumbnail":{"href":"http://192.168.60.201:9000/stac-data/S1A/S1A_IW_GRDH_1SDV_20250625T013854_20250625T013919_059796_076D15_B5C1.SAFE/quick-look.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20260331%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260331T120829Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=19bebb1e446add1d6e0898b4329d2a3e016f59087719ce2b51dff5c487835cb0","type":"image/png","title":"png","description":null,"roles":["thumbnail","overview"]}}} diff --git a/services/pcp-tgu-ops-ui/src/api/ballisticsApi.ts b/services/pcp-tgu-ops-ui/src/api/ballisticsApi.ts index d470295..d9cf52e 100644 --- a/services/pcp-tgu-ops-ui/src/api/ballisticsApi.ts +++ b/services/pcp-tgu-ops-ui/src/api/ballisticsApi.ts @@ -1,4 +1,5 @@ import { TguApiError } from "../model/tguTypes"; +import { toLocalIso } from "../utils/localTime"; const BASE = "/api/pcp-ballistics"; @@ -152,9 +153,9 @@ export async function fetchSatelliteRva( return JSON.parse(text) as RvaZone[]; } -/** LocalDateTime без зоны: YYYY-MM-DDTHH:mm:ss. */ +/** LocalDateTime без зоны (локальные настенные часы): YYYY-MM-DDTHH:mm:ss. */ function toLocalDateTime(ms: number): string { - return new Date(ms).toISOString().slice(0, 19); + return toLocalIso(ms); } function extractErrorText(body: string): string { diff --git a/services/pcp-tgu-ops-ui/src/api/tguApi.ts b/services/pcp-tgu-ops-ui/src/api/tguApi.ts index 149ad5e..05c406e 100644 --- a/services/pcp-tgu-ops-ui/src/api/tguApi.ts +++ b/services/pcp-tgu-ops-ui/src/api/tguApi.ts @@ -5,6 +5,7 @@ import { type TguPlanDecisionMessage, type TguPlatform } from "../model/tguTypes"; +import { toLocalIso } from "../utils/localTime"; export type FlightLinePoint = { time: string; @@ -27,10 +28,9 @@ export async function fetchFlightLine( fromMs: number, toMs: number ): Promise { - const toLocalDT = (ms: number) => new Date(ms).toISOString().slice(0, 19); const query = new URLSearchParams({ - time_start: toLocalDT(fromMs), - time_stop: toLocalDT(toMs) + time_start: toLocalIso(fromMs), + time_stop: toLocalIso(toMs) }); return fetchJson( `/api/tgu-planning/spacecraft/${encodeURIComponent(noradId)}/flight-line?${query}` diff --git a/services/pcp-tgu-ops-ui/src/api/tguPlanApi.ts b/services/pcp-tgu-ops-ui/src/api/tguPlanApi.ts index bb73e52..cf9abd4 100644 --- a/services/pcp-tgu-ops-ui/src/api/tguPlanApi.ts +++ b/services/pcp-tgu-ops-ui/src/api/tguPlanApi.ts @@ -11,7 +11,7 @@ export type DraftMode = "replace" | "fork-forward"; export type CreateDraftRequest = { mode: DraftMode; - /** Начало окна целевой ЗРВ (UTC naive, ISO без зоны). Обязательно для fork-forward. */ + /** Начало окна целевой ЗРВ (naive, ISO без зоны, локальное). Обязательно для fork-forward. */ windowStart?: string; /** Конец окна целевой ЗРВ. Обязательно для fork-forward. */ windowStop?: string; @@ -53,7 +53,7 @@ export type ZrvWindowResponse = { /** * Запрос создания плана новой цепочки (вкладка «Планы»). Окно набирается из двух ЗРВ: * `windowStart`/`windowKppId` — старт выбранной стартовой зоны, `windowStop` — конец конечной. - * Времена — UTC naive (ISO без зоны), как ждёт `LocalDateTime` бэка. `basePlanId` — предыстория + * Времена — naive (ISO без зоны, локальное), как ждёт `LocalDateTime` бэка. `basePlanId` — предыстория * (история тянется) либо `null` (цепочка без истории, пустой план). */ export type CreateChainPlanRequest = { diff --git a/services/pcp-tgu-ops-ui/src/components/timeFields.tsx b/services/pcp-tgu-ops-ui/src/components/timeFields.tsx index 6a561bb..916e58c 100644 --- a/services/pcp-tgu-ops-ui/src/components/timeFields.tsx +++ b/services/pcp-tgu-ops-ui/src/components/timeFields.tsx @@ -1,7 +1,7 @@ import { useEffect, useState, type CSSProperties } from "react"; /** - * Ввод времени суток в строгом 24-часовом формате `ЧЧ:ММ[:СС]` (UTC). + * Ввод времени суток в строгом 24-часовом формате `ЧЧ:ММ[:СС]` (локальное). * * Нативные ``/`type="datetime-local"` рендерят время по локали * браузера/ОС (часто AM/PM) и не подчиняются атрибуту `lang`, поэтому время вводим @@ -101,7 +101,7 @@ export function Time24Field({ value, withSeconds = false, onChange, className, s /** * Замена нативного ``: нативный календарь для даты * (у даты нет проблемы AM/PM) + [Time24Field] для времени в 24-часовом формате. - * Контракт значения тот же — строка `YYYY-MM-DDTHH:mm` (UTC), как у datetime-local. + * Контракт значения тот же — строка `YYYY-MM-DDTHH:mm` (локальное), как у datetime-local. */ type DateTime24FieldProps = { value: string; diff --git a/services/pcp-tgu-ops-ui/src/features/tgu-editor/EditorPanels.tsx b/services/pcp-tgu-ops-ui/src/features/tgu-editor/EditorPanels.tsx index 19ba16e..55f69fe 100644 --- a/services/pcp-tgu-ops-ui/src/features/tgu-editor/EditorPanels.tsx +++ b/services/pcp-tgu-ops-ui/src/features/tgu-editor/EditorPanels.tsx @@ -1,6 +1,6 @@ import { formatDate, formatDateTime, formatDuration, formatTime, kindColor, kindLabel } from "./editorPresentation"; import { statusStyle } from "../tgu-planning/tguStatus"; -import { formatUtcDateTime, parseUtc } from "../../utils/utcTime"; +import { formatLocalDateTime, parseLocal, toLocalIso } from "../../utils/localTime"; import { Time24Field } from "../../components/timeFields"; import type { RvaZone } from "../../api/ballisticsApi"; import type { SurveyRoute } from "../../api/missionPlanningApi"; @@ -50,7 +50,7 @@ type ShootPanelProps = { selectedPass?: EditorVisibilityWindow; modeId?: string; modes: EditorMode[]; - /** Окно строящегося маршрута (UTC, мс). undefined пока не выбран проход. */ + /** Окно строящегося маршрута (локальное, мс). undefined пока не выбран проход. */ routeWindow?: { startMs: number; endMs: number }; /** Текущий крен (gamma) маршрута, градусы. */ routeRoll?: number; @@ -105,7 +105,7 @@ type DropPanelProps = { onSelectZone: (zone?: RvaZone) => void; /** Название станции по её номеру (из каталога станций). */ stationName: (stationId: number) => string; - /** Время начала зоны в мс (UTC) — для подписи. */ + /** Время начала зоны в мс (локальное) — для подписи. */ zoneStartMs: (zone: RvaZone) => number; zoneStopMs: (zone: RvaZone) => number; /** Съёмки-кандидаты для выбранной зоны (end < начало зоны). */ @@ -699,7 +699,7 @@ function surveyTypeLabel(surveyType: string): string { } function formatIso(iso: string): string { - return formatUtcDateTime(parseUtc(iso)); + return formatLocalDateTime(parseLocal(iso)); } function PanelHead({ title, onClose }: { title: string; onClose: () => void }) { @@ -747,7 +747,7 @@ function TimeStepper({ /** * Степпер времени окна маршрута с секундной точностью: кнопки ±5 c / ±30 c и ручной - * ввод времени `чч:мм:сс` (UTC, без даты — дата берётся из текущего значения). + * ввод времени `чч:мм:сс` (локальное, без даты — дата берётся из текущего значения). * Значение зажимается в [min, max]. */ function RouteTimeStepper({ @@ -766,16 +766,16 @@ function RouteTimeStepper({ const clamp = (next: number) => Math.max(min ?? Number.NEGATIVE_INFINITY, Math.min(max ?? Number.POSITIVE_INFINITY, next)); const change = (deltaMs: number) => onChange(clamp(value + deltaMs)); const onTimeChange = (raw: string) => { - // Ввод — только время суток (ЧЧ:ММ:СС, UTC); день оставляем прежним. - const datePart = new Date(value).toISOString().slice(0, 10); - const ms = parseUtc(`${datePart}T${raw}`); + // Ввод — только время суток (ЧЧ:ММ:СС, локальное); день оставляем прежним. + const datePart = toLocalIso(value).slice(0, 10); + const ms = parseLocal(`${datePart}T${raw}`); if (Number.isFinite(ms)) onChange(clamp(ms)); }; return (