pcp: единообразие времени (UTC) по группе сервисов

Фронт (pcp-tgu-ops-ui):
- тест-страж utcTime.guard.test.ts: запрещает Date.parse / new Date(string) /
  toLocale* без timeZone вне utils/utcTime; тестовые фикстуры переведены на parseUtc.

Бэкенд:
- UTC-now: LocalDateTime.now() -> LocalDateTime.now(ZoneOffset.UTC) по всем сервисам
  (entity-дефолты, воркеры, use case'ы) и в тестовых фикстурах.
- Конвертации к UTC (баги на не-UTC JVM, каждая с регресс-тестом в не-UTC поясе):
  - tgu: VisibilityPayloadParser, SyncSpacecraftFromNsiUseCase (Instant -> UTC LocalDateTime);
  - mission-planing: MissionPlaningService (OffsetDateTime -> UTC через toUtcLocalDateTime);
  - dynamic-plan: RequestServiceClient (OffsetDateTime -> UTC);
  - slots: SlotRepositoryImpl (getObject(LocalDateTime) вместо getTimestamp().toLocalDateTime()).
- Контрактные сериализационные тесты формата на проводе (naive без зоны / Z):
  PlanResponse (tgu), RequestResponseDto (request, эталон), TguPlanning DTO (ui).
- KDoc-инвариант «=UTC» на UI-facing DTO (tgu PlanResponse, ui-service DTO вкладки ТГУ).

Документация: docs/standards/DATETIME_UTC.md (соглашение, таблица сервисов, под-задачи на миграцию к Z),
docs/standards/CHECKLIST.md (пункт про UTC на API).
This commit is contained in:
Дмитрий Соловьев
2026-06-02 21:51:38 +03:00
parent ac2220d063
commit 260583b134
84 changed files with 760 additions and 166 deletions
@@ -13,6 +13,7 @@ import jakarta.persistence.Index
import jakarta.persistence.OneToMany
import jakarta.persistence.Table
import java.time.LocalDateTime
import java.time.ZoneOffset
@Entity
@Table(
@@ -34,7 +35,7 @@ class ComplexPlanRunEntity(
var status: ComplexPlanRunStatus = ComplexPlanRunStatus.CREATED,
@Column(name = "created_at", nullable = false)
var createdAt: LocalDateTime = LocalDateTime.now(),
var createdAt: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
@Column(name = "started_at")
var startedAt: LocalDateTime? = null,
@@ -46,10 +47,10 @@ class ComplexPlanRunEntity(
var durationMs: Long? = null,
@Column(name = "interval_start", nullable = false)
var intervalStart: LocalDateTime = LocalDateTime.now(),
var intervalStart: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
@Column(name = "interval_end", nullable = false)
var intervalEnd: LocalDateTime = LocalDateTime.now(),
var intervalEnd: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
@Column(name = "requested_by")
var requestedBy: String? = null,
@@ -15,6 +15,7 @@ import jakarta.persistence.ManyToOne
import jakarta.persistence.Table
import jakarta.persistence.Index
import java.time.LocalDateTime
import java.time.ZoneOffset
@Entity
@Table(
@@ -43,10 +44,10 @@ class SatelliteModeEntity(
var type: SatelliteModeType = SatelliteModeType.SURVEY,
@Column(name = "start_time", nullable = false)
var startTime: LocalDateTime = LocalDateTime.now(),
var startTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
@Column(name = "end_time", nullable = false)
var endTime: LocalDateTime = LocalDateTime.now(),
var endTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
@Column(name = "revolution", nullable = false)
var revolution: Long = 0,
@@ -13,6 +13,7 @@ import jakarta.persistence.ManyToOne
import jakarta.persistence.OneToMany
import jakarta.persistence.Table
import java.time.LocalDateTime
import java.time.ZoneOffset
@Entity
@Table(
@@ -34,13 +35,13 @@ class SatelliteModeSnapshotEntity(
var satelliteId: Long = 0,
@Column(name = "interval_start", nullable = false)
var intervalStart: LocalDateTime = LocalDateTime.now(),
var intervalStart: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
@Column(name = "interval_end", nullable = false)
var intervalEnd: LocalDateTime = LocalDateTime.now(),
var intervalEnd: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
@Column(name = "created_at", nullable = false)
var createdAt: LocalDateTime = LocalDateTime.now(),
var createdAt: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
@Column(name = "is_active", nullable = false)
var isActive: Boolean = false,
@@ -3,11 +3,12 @@ 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(),
val timeStop : LocalDateTime = LocalDateTime.now(),
val time : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
val timeStop : LocalDateTime = LocalDateTime.now(ZoneOffset.UTC),
val roll : Double = 0.0,
val latitude : Double = 0.0,
val longitude : Double = 0.0,