Skip to content

Commit 27499f5

Browse files
authored
Merge pull request #3675 from ControlSystemStudio/arch_rdb_oracle_timezone
RDB archive: Fix Oracle time zone problem.
2 parents d73dad4 + 1912d57 commit 27499f5

File tree

3 files changed

+30
-30
lines changed

3 files changed

+30
-30
lines changed

services/archive-engine/dbd/postgres_schema.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ DROP TABLE IF EXISTS sample;
199199
CREATE TABLE sample
200200
(
201201
channel_id BIGINT NOT NULL,
202-
smpl_time TIMESTAMP NOT NULL,
202+
smpl_time TIMESTAMPTZ NOT NULL,
203203
nanosecs BIGINT NOT NULL,
204204
severity_id BIGINT NOT NULL,
205205
status_id BIGINT NOT NULL,

services/archive-engine/src/main/java/org/csstudio/archive/writer/rdb/RDBArchiveWriter.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2011-2024 Oak Ridge National Laboratory.
2+
* Copyright (c) 2011-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -51,7 +51,6 @@
5151
* @author Lana Abadie - PostgreSQL for original RDBArchive code. Disable autocommit as needed.
5252
* @author Laurent Philippe (Use read-only connection when possible for MySQL load balancing)
5353
*/
54-
@SuppressWarnings("nls")
5554
public class RDBArchiveWriter implements ArchiveWriter
5655
{
5756
/** Status string for <code>Double.NaN</code> samples */
@@ -430,9 +429,8 @@ private void oldBatchDoubleSamples(final RDBWriteChannel channel,
430429
final int N = additional.size();
431430
for (int i = 1; i < N; i++)
432431
{
433-
if (dialect == Dialect.Oracle){
434-
insert_array_sample.setTimestamp(2, stamp);
435-
}
432+
if (dialect == Dialect.Oracle)
433+
insert_array_sample.setObject(2, TimestampHelper.toOffsetDateTime(stamp));
436434
else
437435
{
438436
// Truncate the time stamp
@@ -498,9 +496,8 @@ private void completeAndBatchInsert(
498496
final Timestamp stamp, final int severity,
499497
final Status status) throws Exception
500498
{
501-
if (dialect == Dialect.Oracle){
502-
insert_xx.setTimestamp(2, stamp);
503-
}
499+
if (dialect == Dialect.Oracle)
500+
insert_xx.setObject(2, TimestampHelper.toOffsetDateTime(stamp));
504501
else
505502
{
506503
// Truncate the time stamp

services/archive-engine/src/main/java/org/csstudio/archive/writer/rdb/TimestampHelper.java

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2012-2018 Oak Ridge National Laboratory.
2+
* Copyright (c) 2012-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -9,17 +9,16 @@
99

1010
import java.time.Duration;
1111
import java.time.Instant;
12+
import java.time.OffsetDateTime;
1213
import java.time.ZoneId;
1314
import java.time.ZonedDateTime;
14-
import java.util.Calendar;
1515
import java.util.concurrent.TimeUnit;
1616

1717
import org.phoebus.util.time.TimestampFormats;
1818

1919
/** Time stamp gymnastics
2020
* @author Kay Kasemir
2121
*/
22-
@SuppressWarnings("nls")
2322
public class TimestampHelper
2423
{
2524
/** @param timestamp {@link Instant}, may be <code>null</code>
@@ -32,17 +31,6 @@ public static String format(final Instant timestamp)
3231
return TimestampFormats.FULL_FORMAT.format(timestamp);
3332
}
3433

35-
// May look like just time_format.format(Instant) works,
36-
// but results in runtime error " java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra"
37-
// because time for printing needs to be in local time
38-
// public static void main(String[] args)
39-
// {
40-
// final Instant now = Instant.now();
41-
// System.out.println(format(now));
42-
// System.out.println(time_format.format(now));
43-
// }
44-
45-
4634
/** @param timestamp EPICS Timestamp
4735
* @return SQL Timestamp
4836
*/
@@ -77,14 +65,29 @@ public static Instant fromMillisecs(final long millisecs)
7765
}
7866
return Instant.ofEpochSecond(seconds, nanoseconds);
7967
}
80-
81-
/** @param calendar Calendar
82-
* @return EPICS Timestamp
68+
69+
/** Zone ID is something like "America/New_York".
70+
* Within that zone, time might change between
71+
* EDT (daylight saving) and EST (standard),
72+
* but the Zone ID remains, so we can keep it final.
8373
*/
84-
public static Instant fromCalendar(final Calendar calendar)
85-
{
86-
return fromMillisecs(calendar.getTimeInMillis());
87-
}
74+
final private static ZoneId zone = ZoneId.systemDefault();
75+
76+
/** Turn SQL {@link java.sql.Timestamp} into {@link OffsetDateTime}
77+
*
78+
* Oracle JDBC PreparedStatement.setTimestamp(int, Timestamp)
79+
* will change the zone info in unexpected ways.
80+
* Using PreparedStatement.setObject(int, OffsetDateTime)
81+
* is the suggested workaround, so this morphs a Timestamp
82+
* into OffsetDateTime
83+
*
84+
* @param sql_time SQL {@link java.sql.Timestamp}
85+
* @return {@link OffsetDateTime}
86+
*/
87+
public static OffsetDateTime toOffsetDateTime(final java.sql.Timestamp sql_time)
88+
{
89+
return OffsetDateTime.ofInstant(sql_time.toInstant(), zone);
90+
}
8891

8992
/** Round time to next multiple of given duration
9093
* @param time Original time stamp

0 commit comments

Comments
 (0)