Fix the same UTC-vs-local mismatch in Ūdens's observedAt display
Same root cause as the station-observation fix (this uses the same open-data portal, same UTC DATETIME field): the raw UTC string was passed straight through to the frontend as a display label, which JS's Date parser then reads as local time for a string with no timezone suffix — silently showing observation times 2-3h behind the newsroom's actual clock. Internal recency filtering (isRecent) was already self-consistent either way; this only affects display.
This commit is contained in:
@@ -9,7 +9,7 @@ import org.http4s.ember.client.EmberClientBuilder
|
|||||||
import org.typelevel.log4cats.Logger
|
import org.typelevel.log4cats.Logger
|
||||||
import org.typelevel.log4cats.slf4j.Slf4jLogger
|
import org.typelevel.log4cats.slf4j.Slf4jLogger
|
||||||
|
|
||||||
import java.time.{Duration, Instant, LocalDateTime}
|
import java.time.{Duration, Instant, LocalDateTime, ZoneId, ZoneOffset}
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
|
|
||||||
final case class WaterTemperatureReading(area: String, observedAt: String, min: Option[Double], max: Option[Double])
|
final case class WaterTemperatureReading(area: String, observedAt: String, min: Option[Double], max: Option[Double])
|
||||||
@@ -43,6 +43,15 @@ final class WaterTemperatureService private (logger: Logger[IO], cache: Ref[IO,
|
|||||||
|
|
||||||
private val areaOrder: Vector[String] = Vector("Jūra", "Līcis", "Kurzeme", "Zemgale", "Vidzeme", "Latgale")
|
private val areaOrder: Vector[String] = Vector("Jūra", "Līcis", "Kurzeme", "Zemgale", "Vidzeme", "Latgale")
|
||||||
|
|
||||||
|
// This dataset's DATETIME field is UTC (same source/portal as the station
|
||||||
|
// observations feed, same verified offset); converted to local so the
|
||||||
|
// observedAt label shown on Ūdens matches the newsroom's own clock instead
|
||||||
|
// of reading 2-3h behind.
|
||||||
|
private val rigaZone = ZoneId.of("Europe/Riga")
|
||||||
|
|
||||||
|
private def toLocal(utcDatetime: String): Option[String] =
|
||||||
|
Try(LocalDateTime.parse(utcDatetime).atZone(ZoneOffset.UTC).withZoneSameInstant(rigaZone).toLocalDateTime.toString).toOption
|
||||||
|
|
||||||
// Every LVĢMC hydrological station that reports water temperature (WTEMD
|
// Every LVĢMC hydrological station that reports water temperature (WTEMD
|
||||||
// inland/river stations, SEDUT coastal stations), grouped into the six
|
// inland/river stations, SEDUT coastal stations), grouped into the six
|
||||||
// named Ūdens zones. Boundaries follow Latvia's historical regions
|
// named Ūdens zones. Boundaries follow Latvia's historical regions
|
||||||
@@ -177,7 +186,8 @@ final class WaterTemperatureService private (logger: Logger[IO], cache: Ref[IO,
|
|||||||
val cursor = row.hcursor
|
val cursor = row.hcursor
|
||||||
for {
|
for {
|
||||||
stationId <- cursor.downField("STATION_ID").as[String].toOption
|
stationId <- cursor.downField("STATION_ID").as[String].toOption
|
||||||
datetime <- cursor.downField("DATETIME").as[String].toOption
|
rawDatetime <- cursor.downField("DATETIME").as[String].toOption
|
||||||
|
datetime <- toLocal(rawDatetime)
|
||||||
value <- cursor.downField("VALUE").as[Double].toOption
|
value <- cursor.downField("VALUE").as[Double].toOption
|
||||||
} yield StationReading(stationId, datetime, value)
|
} yield StationReading(stationId, datetime, value)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user