160 lines
4.7 KiB
JavaScript
160 lines
4.7 KiB
JavaScript
/**
|
|
* Fix Script: Pad Single-Digit Hours in CreatedTime
|
|
* This script fixes times like "2:31:47 PM" to "02:31:47 PM"
|
|
*
|
|
* Usage: node scripts/fixSingleDigitHours.js [--dry-run]
|
|
*/
|
|
|
|
import { rawQuery } from '../src/db.js';
|
|
import dotenv from 'dotenv';
|
|
|
|
dotenv.config();
|
|
|
|
async function fixSingleDigitHours(dryRun = false) {
|
|
console.log('🔍 Checking for single-digit hour times...\n');
|
|
|
|
try {
|
|
// First, find all entries with single-digit hours
|
|
const problematic = await rawQuery(`
|
|
SELECT
|
|
ctid,
|
|
"CreatedDate",
|
|
"CreatedTime",
|
|
"Symbol"
|
|
FROM "OptionsFlow_monthly"
|
|
WHERE "CreatedTime" IS NOT NULL
|
|
AND (
|
|
-- Single-digit hour with seconds: "2:31:47 PM"
|
|
"CreatedTime"::text ~ '^[1-9]:[0-9]{2}:[0-9]{2}\\s*(AM|PM)$'
|
|
-- Single-digit hour with minutes only: "2:30 PM"
|
|
OR "CreatedTime"::text ~ '^[1-9]:[0-9]{2}\\s*(AM|PM)$'
|
|
)
|
|
ORDER BY "CreatedDate" DESC, "CreatedTime" DESC
|
|
LIMIT 100;
|
|
`);
|
|
|
|
console.log(`📊 Found ${problematic.length} entries with single-digit hours`);
|
|
|
|
if (problematic.length === 0) {
|
|
console.log('✅ No entries with single-digit hours found!');
|
|
return;
|
|
}
|
|
|
|
// Show sample
|
|
console.log('\n📋 Sample of problematic entries:');
|
|
problematic.slice(0, 10).forEach(row => {
|
|
console.log(` - "${row.CreatedTime}" on ${row.CreatedDate} (${row.Symbol})`);
|
|
});
|
|
|
|
if (dryRun) {
|
|
console.log('\n🔍 DRY RUN MODE - No changes will be made');
|
|
console.log(` Would fix ${problematic.length} entries`);
|
|
return;
|
|
}
|
|
|
|
// Count total affected
|
|
const totalCount = await rawQuery(`
|
|
SELECT COUNT(*) as total
|
|
FROM "OptionsFlow_monthly"
|
|
WHERE "CreatedTime" IS NOT NULL
|
|
AND (
|
|
"CreatedTime"::text ~ '^[1-9]:[0-9]{2}:[0-9]{2}\\s*(AM|PM)$'
|
|
OR "CreatedTime"::text ~ '^[1-9]:[0-9]{2}\\s*(AM|PM)$'
|
|
);
|
|
`);
|
|
|
|
const total = totalCount[0]?.total || 0;
|
|
console.log(`\n🔧 Fixing ${total} entries...`);
|
|
|
|
// Fix entries with seconds: "2:31:47 PM" -> "02:31:47 PM"
|
|
const fixWithSeconds = await rawQuery(`
|
|
UPDATE "OptionsFlow_monthly"
|
|
SET "CreatedTime" = REGEXP_REPLACE(
|
|
btrim("CreatedTime"::text),
|
|
'^([1-9])(:[0-9]{2}:[0-9]{2}\\s*(AM|PM))',
|
|
'0\\1\\2',
|
|
'i'
|
|
)
|
|
WHERE "CreatedTime" IS NOT NULL
|
|
AND "CreatedTime"::text ~ '^[1-9]:[0-9]{2}:[0-9]{2}\\s*(AM|PM)$';
|
|
`);
|
|
|
|
console.log(` ✅ Fixed entries with seconds format`);
|
|
|
|
// Fix entries with minutes only: "2:30 PM" -> "02:30 PM"
|
|
const fixWithMinutes = await rawQuery(`
|
|
UPDATE "OptionsFlow_monthly"
|
|
SET "CreatedTime" = REGEXP_REPLACE(
|
|
btrim("CreatedTime"::text),
|
|
'^([1-9])(:[0-9]{2}\\s*(AM|PM))',
|
|
'0\\1\\2',
|
|
'i'
|
|
)
|
|
WHERE "CreatedTime" IS NOT NULL
|
|
AND "CreatedTime"::text ~ '^[1-9]:[0-9]{2}\\s*(AM|PM)$';
|
|
`);
|
|
|
|
console.log(` ✅ Fixed entries with minutes format`);
|
|
|
|
// Verify the fix
|
|
const remaining = await rawQuery(`
|
|
SELECT COUNT(*) as total
|
|
FROM "OptionsFlow_monthly"
|
|
WHERE "CreatedTime" IS NOT NULL
|
|
AND (
|
|
"CreatedTime"::text ~ '^[1-9]:[0-9]{2}:[0-9]{2}\\s*(AM|PM)$'
|
|
OR "CreatedTime"::text ~ '^[1-9]:[0-9]{2}\\s*(AM|PM)$'
|
|
);
|
|
`);
|
|
|
|
const remainingCount = remaining[0]?.total || 0;
|
|
|
|
if (remainingCount === 0) {
|
|
console.log(`\n✅ Successfully fixed all ${total} entries!`);
|
|
} else {
|
|
console.log(`\n⚠️ Warning: ${remainingCount} entries still have single-digit hours`);
|
|
console.log(' This might be due to whitespace or other formatting issues');
|
|
}
|
|
|
|
// Show sample of fixed entries
|
|
const fixedSample = await rawQuery(`
|
|
SELECT
|
|
"CreatedDate",
|
|
"CreatedTime",
|
|
COUNT(*) as count
|
|
FROM "OptionsFlow_monthly"
|
|
WHERE "CreatedTime" IS NOT NULL
|
|
AND "CreatedTime"::text ~ '^[0-9]{2}:[0-9]{2}:[0-9]{2}\\s*(AM|PM)$'
|
|
GROUP BY "CreatedDate", "CreatedTime"
|
|
ORDER BY "CreatedDate" DESC
|
|
LIMIT 5;
|
|
`);
|
|
|
|
console.log('\n📋 Sample of fixed entries (now properly formatted):');
|
|
fixedSample.forEach(row => {
|
|
console.log(` - "${row.CreatedTime}" on ${row.CreatedDate}: ${row.count} occurrences`);
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error fixing single-digit hours:', error.message);
|
|
console.error(error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Parse command line arguments
|
|
const args = process.argv.slice(2);
|
|
const dryRun = args.includes('--dry-run') || args.includes('-d');
|
|
|
|
// Run the fix
|
|
fixSingleDigitHours(dryRun)
|
|
.then(() => {
|
|
console.log('\n✅ Fix complete');
|
|
process.exit(0);
|
|
})
|
|
.catch((error) => {
|
|
console.error('\n❌ Fix failed:', error);
|
|
process.exit(1);
|
|
});
|
|
|