@@ -54,6 +54,15 @@ def md5_as_hex(self, s: str) -> str:
54
54
def normalize_timestamp (self , value : str , coltype : TemporalType ) -> str :
55
55
if coltype .rounds :
56
56
timestamp = f"{ value } ::timestamp(6)"
57
+
58
+ # redshift allows some problematic timestamp values, don't normalize those (epoch calcs fail)
59
+ case_start = (
60
+ f"case when "
61
+ + f"({ timestamp } < '1901-01-01 00:00'::timestamp(6) or { timestamp } >= '2038-01-01'::timestamp(6))"
62
+ + f"then { timestamp } ::varchar else"
63
+ )
64
+ case_end = f"end"
65
+
57
66
# Get seconds since epoch. Redshift doesn't support milli- or micro-seconds.
58
67
secs = f"timestamp 'epoch' + round(extract(epoch from { timestamp } )::decimal(38)"
59
68
# Get the milliseconds from timestamp.
@@ -65,8 +74,14 @@ def normalize_timestamp(self, value: str, coltype: TemporalType) -> str:
65
74
timestamp6 = (
66
75
f"to_char({ epoch } , -6+{ coltype .precision } ) * interval '0.000001 seconds', 'YYYY-mm-dd HH24:MI:SS.US')"
67
76
)
77
+ padded = self ._add_padding (coltype , timestamp6 )
78
+ return f"{ case_start } { padded } { case_end } "
68
79
else :
69
80
timestamp6 = f"to_char({ value } ::timestamp(6), 'YYYY-mm-dd HH24:MI:SS.US')"
81
+ padded = self ._add_padding (coltype , timestamp6 )
82
+ return padded
83
+
84
+ def _add_padding (self , coltype : TemporalType , timestamp6 : str ):
70
85
return (
71
86
f"RPAD(LEFT({ timestamp6 } , { TIMESTAMP_PRECISION_POS + coltype .precision } ), { TIMESTAMP_PRECISION_POS + 6 } , '0')"
72
87
)
0 commit comments