@@ -102,13 +102,40 @@ def md5_as_hex(self, s: str) -> str:
102
102
return f"md5({ s } )"
103
103
104
104
def normalize_timestamp (self , value : str , coltype : TemporalType ) -> str :
105
+ def _add_padding (coltype : TemporalType , timestamp6 : str ):
106
+ return f"RPAD(LEFT({ timestamp6 } , { TIMESTAMP_PRECISION_POS + coltype .precision } ), { TIMESTAMP_PRECISION_POS + 6 } , '0')"
107
+
105
108
if coltype .rounds :
106
- return f"to_char({ value } ::timestamp({ coltype .precision } ), 'YYYY-mm-dd HH24:MI:SS.US')"
109
+ # NULL value expected to return NULL after normalization
110
+ null_case_begin = f"CASE WHEN { value } IS NULL THEN NULL ELSE "
111
+ null_case_end = "END"
112
+
113
+ # 294277 or 4714 BC would be out of range, make sure we can't round to that
114
+ # TODO test timezones for overflow?
115
+ max_timestamp = "294276-12-31 23:59:59.0000"
116
+ min_timestamp = "4713-01-01 00:00:00.00 BC"
117
+ timestamp = f"least('{ max_timestamp } '::timestamp(6), { value } ::timestamp(6))"
118
+ timestamp = f"greatest('{ min_timestamp } '::timestamp(6), { timestamp } )"
119
+
120
+ interval = format ((0.5 * (10 ** (- coltype .precision ))), f".{ coltype .precision + 1 } f" )
121
+
122
+ rounded_timestamp = (
123
+ f"left(to_char(least('{ max_timestamp } '::timestamp, { timestamp } )"
124
+ f"+ interval '{ interval } ', 'YYYY-mm-dd HH24:MI:SS.US'),"
125
+ f"length(to_char(least('{ max_timestamp } '::timestamp, { timestamp } )"
126
+ f"+ interval '{ interval } ', 'YYYY-mm-dd HH24:MI:SS.US')) - (6-{ coltype .precision } ))"
127
+ )
107
128
108
- timestamp6 = f"to_char({ value } ::timestamp(6), 'YYYY-mm-dd HH24:MI:SS.US')"
109
- return (
110
- f"RPAD(LEFT({ timestamp6 } , { TIMESTAMP_PRECISION_POS + coltype .precision } ), { TIMESTAMP_PRECISION_POS + 6 } , '0')"
111
- )
129
+ padded = _add_padding (coltype , rounded_timestamp )
130
+ return f"{ null_case_begin } { padded } { null_case_end } "
131
+
132
+ # TODO years with > 4 digits not padded correctly
133
+ # current w/ precision 6: 294276-12-31 23:59:59.0000
134
+ # should be 294276-12-31 23:59:59.000000
135
+ else :
136
+ rounded_timestamp = f"to_char({ value } ::timestamp(6), 'YYYY-mm-dd HH24:MI:SS.US')"
137
+ padded = _add_padding (coltype , rounded_timestamp )
138
+ return padded
112
139
113
140
def normalize_number (self , value : str , coltype : FractionalType ) -> str :
114
141
return self .to_string (f"{ value } ::decimal(38, { coltype .precision } )" )
0 commit comments