Algo que me paso en proyecto, es tener que insertar datos de MySQL directo a Snowflake a traves de python y que las fechas no recibieran el formato correcto. Cuando hacia el SELECT sobre la tabla en Snowflake, los campos de tipo DATE o DATETIME tenian siempre un valor como ‘541234123-12-01 00:00:00’.
Entiendo que el problema, esta principalmente al utilizar la funcion write_pandas, pero algo bastante molesto que me encontre, es que en Pandas, todos los campos de tipo fecha son ‘object’ entonces es dificil listarlos simplemente.
Una opcion, es recorrer todos los campos de tipo ‘object’ intentar convertirlos a fechas y en donde falla simplemente ignorarlo y seguir:
import pandas as pd
# Assuming df is your DataFrame
df = pd.DataFrame({
'ID': [1, 2, 3],
'Date1': ['2022-01-01', '2022-02-01', '2022-03-01'],
'Amount': [100, 150, 200],
'Date2': ['2022-01-15', '2022-02-15', '2022-03-15'],
'Category': ['A', 'B', 'A']
})
# Find columns with date-like values among object columns
date_like_columns = []
for col in df.select_dtypes(include='object').columns:
try:
pd.to_datetime(df[col], errors='raise')
date_like_columns.append(col)
except ValueError:
pass
# Print the list of date-like columns
print("Date-like columns:", date_like_columns)
El problema, es que para datasets grandes, quizas sea mas simple identificar a las columnas por su nombre. Si trabajan con una base de datos donde los campos de tipo DATE estan identificados en su nombre, o si tienen una lista de columnas que quieran convertir si o si, pueden hacer algo como lo siguiente:
def write_pandas_df_to_table(df, table_name: str):
pd.set_option('display.max_columns', None)
df.drop(df.columns[df.columns.str.contains('unnamed', case=False)], axis=1, inplace=True)
for col in df.columns:
if (col.startswith('DATE') or
(col.endswith('DATE') and not col.endswith('UPDATE')) or
col.endswith('SYNC') or
col.endswith('_AT') or
col.endswith('DATETIME') or
col in DATE_COLUMNS_LIST):
df[col] = df[col].replace(['0000-00-00'], None)
if col not in NOT_DATE_COLUMN_LIST:
try:
df[col] = df[col].replace(['0000-00-00 00:00:00'], None)
df[col] = pd.to_datetime(df[col], format='%Y-%m-%d %H:%M:%S.%f', errors='coerce')
df[col] = df[col].dt.tz_localize('UTC')
except Exception as e:
print('Column with error: {}'.format(col))
raise e
return write_pandas(<conexion a snowflake>, df, table_name)
Este ultimo codigo tiene ademas algunos pasos extras para remover las fechas ‘0000-00-00’ que se pueden a veces ver por ejemplo en MySQL. Tambien le da el formato standard a las fechas de ‘YYYY-MM-DD’. Actualiza el dataframe, y luego corre el insert a Snowflake.