/** * Diagnostic Script: Check for Malformed Time Entries * Run this to identify time format issues in the database * * Usage: node scripts/checkTimeFormat.js */ import { rawQuery } from '../src/db.js'; import dotenv from 'dotenv'; dotenv.config(); async function checkTimeFormats() { console.log('šŸ” Checking for malformed time entries...\n'); try { // Check 1: Find entries with just "XX AM" or "XX PM" (no colon, likely missing hour) const malformed1 = await rawQuery(` SELECT "CreatedDate", "CreatedTime", COUNT(*) as count 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}' GROUP BY "CreatedDate", "CreatedTime" ORDER BY count DESC LIMIT 20; `); console.log('šŸ“Š Pattern 1: Times like "34 AM" or "12 PM" (no colon, missing hour):'); if (malformed1.length > 0) { console.log(` Found ${malformed1.length} unique malformed time patterns`); malformed1.forEach(row => { console.log(` - "${row.CreatedTime}" on ${row.CreatedDate}: ${row.count} occurrences`); }); } else { console.log(' āœ… No issues found'); } console.log(''); // Check 2: Find entries with ":XX AM" or ":XX PM" (colon but no hour) const malformed2 = await rawQuery(` SELECT "CreatedDate", "CreatedTime", COUNT(*) as count FROM "OptionsFlow_monthly" WHERE "CreatedTime" IS NOT NULL AND "CreatedTime"::text ~ '^:\\d{1,2}\\s*(AM|PM)$' GROUP BY "CreatedDate", "CreatedTime" ORDER BY count DESC LIMIT 20; `); console.log('šŸ“Š Pattern 2: Times like ":34 AM" (colon but missing hour):'); if (malformed2.length > 0) { console.log(` Found ${malformed2.length} unique malformed time patterns`); malformed2.forEach(row => { console.log(` - "${row.CreatedTime}" on ${row.CreatedDate}: ${row.count} occurrences`); }); } else { console.log(' āœ… No issues found'); } console.log(''); // Check 3: Count total malformed entries const totalMalformed = await rawQuery(` SELECT COUNT(*) as total 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)$' ); `); console.log(`šŸ“ˆ Total malformed entries: ${totalMalformed[0]?.total || 0}`); console.log(''); // Check 4: Show sample of properly formatted times for comparison const properFormat = await rawQuery(` SELECT "CreatedDate", "CreatedTime", COUNT(*) as count FROM "OptionsFlow_monthly" WHERE "CreatedTime" IS NOT NULL AND "CreatedTime"::text ~ '^\\d{1,2}:\\d{2}:\\d{2}\\s*(AM|PM)$' GROUP BY "CreatedDate", "CreatedTime" ORDER BY "CreatedDate" DESC, count DESC LIMIT 10; `); console.log('āœ… Sample of properly formatted times:'); properFormat.forEach(row => { console.log(` - "${row.CreatedTime}" on ${row.CreatedDate}: ${row.count} occurrences`); }); console.log(''); // Summary const totalEntries = await rawQuery(` SELECT COUNT(*) as total FROM "OptionsFlow_monthly" WHERE "CreatedTime" IS NOT NULL; `); const total = totalEntries[0]?.total || 0; const malformed = totalMalformed[0]?.total || 0; const percentage = total > 0 ? ((malformed / total) * 100).toFixed(2) : 0; console.log('šŸ“‹ Summary:'); console.log(` Total entries with time: ${total}`); console.log(` Malformed entries: ${malformed} (${percentage}%)`); console.log(` Properly formatted: ${total - malformed} (${(100 - parseFloat(percentage)).toFixed(2)}%)`); console.log(''); if (malformed > 0) { console.log('āš ļø ACTION REQUIRED:'); console.log(' Run the fix script: backend/database/fix_time_format_simple.sql'); console.log(' Or use the comprehensive fix: backend/database/fix_malformed_times.sql'); } else { console.log('āœ… All time entries appear to be properly formatted!'); } } catch (error) { console.error('āŒ Error checking time formats:', error.message); console.error(error); } } // Run the check checkTimeFormats() .then(() => { console.log('\nāœ… Diagnostic complete'); process.exit(0); }) .catch((error) => { console.error('\nāŒ Diagnostic failed:', error); process.exit(1); });