institutional-trader/backend/scripts/checkTimeFormat.js

144 lines
4.6 KiB
JavaScript

/**
* 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);
});