From dd248c193870e79cbbb0373625c8dc8ac98265b6 Mon Sep 17 00:00:00 2001 From: Ethan Moss Date: Mon, 19 Oct 2020 16:47:45 -0700 Subject: [PATCH 1/2] Added int8 (bigint) and timestamp types --- google_spreadsheets_fdw/__init__.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/google_spreadsheets_fdw/__init__.py b/google_spreadsheets_fdw/__init__.py index 366102d..0b33b8e 100644 --- a/google_spreadsheets_fdw/__init__.py +++ b/google_spreadsheets_fdw/__init__.py @@ -32,17 +32,21 @@ def gs_date_to_pg_date(val: float) -> date: pg_to_gs_converters = { 2950: lambda val: str(val) if val else None, # uuid 1043: lambda val: str(val) if val else None, # varchar - 23: lambda val: int(val) if val else None, # int + 23: lambda val: int(val) if val else None, # int4 + 20: lambda val: int(val) if val else None, # int8 701: lambda val: float(val) if val else None, # float - 1082: lambda val: pg_date_to_gs_date(val) if val else None # date + 1082: lambda val: pg_date_to_gs_date(val) if val else None, # date + 1114: lambda val: pg_date_to_gs_date(val) if val else None # timestamp } gs_to_pg_converters = { 2950: lambda val: str(val) if val else None, # uuid 1043: lambda val: str(val) if val else None, # varchar - 23: lambda val: int(val) if val else None, # int + 23: lambda val: int(val) if val else None, # int4 + 20: lambda val: int(val) if val else None, # int8 701: lambda val: float(val) if val else None, # float - 1082: lambda val: gs_date_to_pg_date(val) if val else None # date + 1082: lambda val: gs_date_to_pg_date(val) if val else None, # date + 1114: lambda val: gs_date_to_pg_date(val) if val else None # timestamp } From 7488fbdccfda0d9d5f33c4da1065255313415be6 Mon Sep 17 00:00:00 2001 From: Ethan Moss Date: Wed, 28 Oct 2020 17:27:17 -0700 Subject: [PATCH 2/2] Added Timestamp conversion functionality -- Exact second is off-by-one in ~50% of cases when converting google timestamps to postgres --- google_spreadsheets_fdw/__init__.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/google_spreadsheets_fdw/__init__.py b/google_spreadsheets_fdw/__init__.py index 0b33b8e..258526d 100644 --- a/google_spreadsheets_fdw/__init__.py +++ b/google_spreadsheets_fdw/__init__.py @@ -12,21 +12,37 @@ def float_to_hms(f: float) -> (int, int, int): - h, r = divmod(f, 1) + h, r = divmod(f * 24, 1) m, r = divmod(r * 60, 1) return int(h), int(m), int(r * 60), +def hms_to_float(h: int, m: int, s: int) -> float: + f = s / 60 + f = (f + m) / 60 + f = (f + h) / 24 + return f + + def pg_date_to_gs_date(val: date) -> float: delta = datetime.combine(val, time()) - datetime(1899, 12, 30) return float(delta.days) + (float(delta.seconds) / 86400) -def gs_date_to_pg_date(val: float) -> date: +def pg_timestamp_to_gs_timestamp(val: datetime) -> float: + f = pg_date_to_gs_date(val.date()) + return f + hms_to_float(val.hour, val.minute, val.second) + + +def gs_timestamp_to_pg_timestamp(val: float) -> datetime: ordinal = datetime(1899, 12, 30).toordinal() + int(val) dt = datetime.fromordinal(ordinal) h, m, s = float_to_hms(val % 1) - return dt.replace(hour=h, minute=m, second=s).date() + return dt.replace(hour=h, minute=m, second=s) + + +def gs_date_to_pg_date(val: float) -> date: + return gs_timestamp_to_pg_timestamp(val).date() pg_to_gs_converters = { @@ -36,7 +52,7 @@ def gs_date_to_pg_date(val: float) -> date: 20: lambda val: int(val) if val else None, # int8 701: lambda val: float(val) if val else None, # float 1082: lambda val: pg_date_to_gs_date(val) if val else None, # date - 1114: lambda val: pg_date_to_gs_date(val) if val else None # timestamp + 1114: lambda val: pg_timestamp_to_gs_timestamp(val) if val else None # timestamp } gs_to_pg_converters = { @@ -46,7 +62,7 @@ def gs_date_to_pg_date(val: float) -> date: 20: lambda val: int(val) if val else None, # int8 701: lambda val: float(val) if val else None, # float 1082: lambda val: gs_date_to_pg_date(val) if val else None, # date - 1114: lambda val: gs_date_to_pg_date(val) if val else None # timestamp + 1114: lambda val: gs_timestamp_to_pg_timestamp(val) if val else None # timestamp }