Skip to content

Fixed DST handling by moving to timeofday#2503

Merged
Hydrocharged merged 1 commit intomainfrom
daylon/dst
Mar 28, 2026
Merged

Fixed DST handling by moving to timeofday#2503
Hydrocharged merged 1 commit intomainfrom
daylon/dst

Conversation

@Hydrocharged
Copy link
Copy Markdown
Collaborator

time.Time serialization and deserialization can cause information to be irreversibly lost due to daylight savings time changes. The location isn't directly serialized due to it being tied to the runtime system information (different operating systems may have different time zone information), and is therefore reconstructed on deserialization.

This is fine for timestamptz, as we internally process everything as UTC and use the client's timezone when returning values to the client. For timetz, however, the timezone information is embedded in the value itself and is independent of the client, and this was causing information loss during serialization. This PR changes serialization to use the timetz.TimeTZ type, which is already used at most steps (by casting time.Time to timetz.TimeTZ and vice-versa), and therefore the change propagates to all functions that take a timetz value.

In line with this, the time type was updated to use timeofday.TimeOfDay, which is also already used internally in most functions. Although serialization is fine, this was changed to be more inline with timetz (as timetz.TimeTZ directly uses timeofday.TimeOfDay) and also due to time.Time carrying implicit information that can cause direct value comparisons to be incorrect. For example, '01:00:00'::time should sort before '02:00:00'::time, however adding 24 hours to the first value will still result in the correct hour mark for display, but internally the time.Time value would be on the next day, and would cause the comparison to actually show '02:00:00'::time appearing first (assuming they started on the same day to begin with).

All of these issues are fixed by using the correct types that are already in Doltgres, and already used by the internal functions. I'm not sure why we decided to use time.Time instead of those anyway (as interval uses the internal type rather than casting to time.Duration), but this fixes it. This does mean that the serialization is incompatible with existing databases, however since serialization was incorrect in the first place, it's a necessary change.

@Hydrocharged Hydrocharged requested a review from zachmu March 27, 2026 11:40
@Hydrocharged Hydrocharged changed the title Fixed DST handling by moving to Fixed DST handling by moving to timeofday Mar 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Main PR
covering_index_scan_postgres 1119.72/s 1123.13/s +0.3%
index_join_postgres 159.50/s 159.45/s -0.1%
index_join_scan_postgres 207.52/s 205.39/s -1.1%
index_scan_postgres 12.09/s 12.13/s +0.3%
oltp_point_select 2411.07/s 2427.45/s +0.6%
oltp_read_only 1871.85/s 1860.03/s -0.7%
select_random_points 129.72/s 129.46/s -0.3%
select_random_ranges 840.20/s 832.18/s -1.0%
table_scan_postgres 11.90/s 11.86/s -0.4%
types_table_scan_postgres 5.45/s 5.50/s +0.9%

@github-actions
Copy link
Copy Markdown
Contributor

Main PR
Total 42090 42090
Successful 17779 17782
Failures 24311 24308
Partial Successes1 5562 5564
Main PR
Successful 42.2404% 42.2476%
Failures 57.7596% 57.7524%

${\color{lightgreen}Progressions (3)}$

random

QUERY: (SELECT unique1 AS random
  FROM onek ORDER BY random() LIMIT 1)
INTERSECT
(SELECT unique1 AS random
  FROM onek ORDER BY random() LIMIT 1)
INTERSECT
(SELECT unique1 AS random
  FROM onek ORDER BY random() LIMIT 1);

time

QUERY: SELECT '24:00:00'::time;

timetz

QUERY: SELECT '24:00:00 PDT'::timetz;

Footnotes

  1. These are tests that we're marking as Successful, however they do not match the expected output in some way. This is due to small differences, such as different wording on the error messages, or the column names being incorrect while the data itself is correct.

Copy link
Copy Markdown
Member

@zachmu zachmu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, no objections

@Hydrocharged Hydrocharged merged commit a42c3e4 into main Mar 28, 2026
21 checks passed
@Hydrocharged Hydrocharged deleted the daylon/dst branch March 28, 2026 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants