-- Simple Fix for Malformed Time Entries -- Fixes times like "34 AM" (missing hour) by adding a default hour -- Run this in your PostgreSQL database -- Step 1: Check for malformed entries SELECT "CreatedDate", "CreatedTime", COUNT(*) as count FROM "OptionsFlow_monthly" WHERE "CreatedTime" IS NOT NULL AND "CreatedTime"::text ~ '^\d{2}\s*(AM|PM)$' -- Two digits + AM/PM (likely minute only) AND "CreatedTime"::text !~ '^\d{1,2}:\d{2}' -- No colon (missing hour) GROUP BY "CreatedDate", "CreatedTime" ORDER BY count DESC LIMIT 50; -- Step 2: Fix entries where time is just "XX AM" or "XX PM" (missing hour) -- Strategy: If the number is > 12, it's definitely a minute, so add hour 9 (AM) or 1 (PM) -- If number <= 12, check context or default to 9 AM / 1 PM UPDATE "OptionsFlow_monthly" SET "CreatedTime" = CASE -- Pattern: "34 AM" -> "9:34 AM" (number > 12, must be minutes) WHEN "CreatedTime"::text ~ '^(\d{2})\s*AM$' AND (REGEXP_REPLACE("CreatedTime"::text, '^(\d{2})\s*AM$', '\1'))::int > 12 THEN '9:' || REGEXP_REPLACE("CreatedTime"::text, '^(\d{2})\s*AM$', '\1') || ':00 AM' -- Pattern: "34 PM" -> "1:34 PM" (number > 12, must be minutes) WHEN "CreatedTime"::text ~ '^(\d{2})\s*PM$' AND (REGEXP_REPLACE("CreatedTime"::text, '^(\d{2})\s*PM$', '\1'))::int > 12 THEN '1:' || REGEXP_REPLACE("CreatedTime"::text, '^(\d{2})\s*PM$', '\1') || ':00 PM' -- Pattern: "12 AM" or less -> "9:XX AM" (could be hour or minute, default to 9 AM) WHEN "CreatedTime"::text ~ '^(\d{1,2})\s*AM$' AND (REGEXP_REPLACE("CreatedTime"::text, '^(\d{1,2})\s*AM$', '\1'))::int <= 12 THEN '9:' || LPAD(REGEXP_REPLACE("CreatedTime"::text, '^(\d{1,2})\s*AM$', '\1'), 2, '0') || ':00 AM' -- Pattern: "12 PM" or less -> "1:XX PM" (could be hour or minute, default to 1 PM) WHEN "CreatedTime"::text ~ '^(\d{1,2})\s*PM$' AND (REGEXP_REPLACE("CreatedTime"::text, '^(\d{1,2})\s*PM$', '\1'))::int <= 12 THEN '1:' || LPAD(REGEXP_REPLACE("CreatedTime"::text, '^(\d{1,2})\s*PM$', '\1'), 2, '0') || ':00 PM' -- Pattern: ":34 AM" (missing hour, has colon) -> "9:34 AM" WHEN "CreatedTime"::text ~ '^:(\d{1,2})\s*AM$' THEN '9:' || LPAD(REGEXP_REPLACE("CreatedTime"::text, '^:(\d{1,2})\s*AM$', '\1'), 2, '0') || ':00 AM' -- Pattern: ":34 PM" (missing hour, has colon) -> "1:34 PM" WHEN "CreatedTime"::text ~ '^:(\d{1,2})\s*PM$' THEN '1:' || LPAD(REGEXP_REPLACE("CreatedTime"::text, '^:(\d{1,2})\s*PM$', '\1'), 2, '0') || ':00 PM' ELSE "CreatedTime" -- Keep as-is if doesn't match patterns END WHERE "CreatedTime" IS NOT NULL AND ( -- Match patterns: "XX AM/PM" without colon, or ":XX AM/PM" ("CreatedTime"::text ~ '^\d{1,2}\s*(AM|PM)$' AND "CreatedTime"::text !~ '^\d{1,2}:\d{2}') OR "CreatedTime"::text ~ '^:\d{1,2}\s*(AM|PM)$' ); -- Step 3: Verify the fix SELECT COUNT(*) as remaining_malformed, 'Remaining entries with malformed time format' as description FROM "OptionsFlow_monthly" WHERE "CreatedTime" IS NOT NULL AND ( ("CreatedTime"::text ~ '^\d{1,2}\s*(AM|PM)$' AND "CreatedTime"::text !~ '^\d{1,2}:\d{2}') OR "CreatedTime"::text ~ '^:\d{1,2}\s*(AM|PM)$' ); -- Step 4: Show sample of fixed entries SELECT "CreatedDate", "CreatedTime", "Symbol", COUNT(*) as count FROM "OptionsFlow_monthly" WHERE "CreatedTime" IS NOT NULL AND "CreatedTime"::text ~ '^\d{1,2}:\d{2}:\d{2}\s*(AM|PM)$' -- Properly formatted now GROUP BY "CreatedDate", "CreatedTime", "Symbol" ORDER BY "CreatedDate" DESC LIMIT 20;