Search code examples
powershellhashtable

Replace badly formatted time data in a csv


I'm trying to reformat some data in a CSV file that contains data about horse racing. The problem i have is that the timestamp for the race doesnt follow any normal convention in that it doesnt recognise AM/PM (because all races in the UK take place between 11am and 10pm)

So a timestamp if 11.55 is always AM, and one of 1.15 is always PM (13:15)

I'm trying to update them all into 24 hour format to move data from one software package to another

So i can read in the CSV, do some other replaces no probelm but just cant get my head round the time element. I had tried a hashtable but I'm struggling to get it to replace any data.

here is some code

$a = (get-Date).ToString("dd/MM/yyyy")

$timelist= @{
'1:00'='13:00'
'1:05'='13:05'
'1:10'='13:10'
'1:15'='13:15'
'1:20'='13:20'
'1:25'='13:25'
'1:30'='13:30'  etc all the way to 10:55

foreach ($file in $infiles){ 
$folder = Split-Path $file -Parent
$name = [System.IO.Path]::GetFileNameWithoutExtension($file)
$outfile = $folder+"\"+"$name"+".csv"

$csv = import-csv $file -delimiter "`t" | Select @{ name='Date' ;Expression={$a}},RaceTime,Track,Horse

    foreach ($row in $csv){
        $row.Horse = $row.Horse.Substring(0, $row.Horse.IndexOf(' ('))
        $row.Track = $row.Track.Substring(0, $row.Track.IndexOf(' ('))
        $row.RaceTime.Value = $timelist[$row.RaceTime]
                    }

            $csv | ConvertTo-Csv -NoType | 
                Select-Object -Skip 1 | 
                Set-Content $outfile 

The output file doesn't change the time stamps at all.

EDIT: to include input sample data

RaceTime    Track   RaceType    RaceClass   Horse   Odds    Jockey  Trainer Placing 
"2.15"  "Cartmel"   "Novices Hurdle"    "Class 4"   "Grapevine (IRE)"   "2.25"  "Brace, Connor" "Leech, Mrs S"  "4th"
"2.50"  "Cartmel"   "Handicap Hurdle"   "Class 4"   "Bannixtown Glory (IRE)"    "3.00"  "Hughes, Brian" "McCain Jnr, D" "3rd"
"3.25"  "Cartmel"   "Novices Chase" "Class 4"   "Francky Du Berlais (FR)"   "2.75"  "Bowen, Mr J C" "Bowen, P"  "3rd"
"4.00"  "Cartmel"   "Handicap Chase"    "Class 5"   "Mash Potato (IRE)" "3.25"  "Bowen, Mr S P" "Kelly, Noel C" "1st"
"4.35"  "Cartmel"   "Handicap Chase"    "Class 4"   "Day Of Roses (IRE)"    "3.50"  "Hughes, Brian" "Foster, Miss J E"  "3rd"
"5.10"  "Cartmel"   "Handicap Hurdle"   "Class 3"   "Cardigan Bay (FR)" "9.00"  "Coleman, A"    "Longsdon, C E" "7th"
"5.45"  "Cartmel"   "Handicap Hurdle"   "Class 4"   "Cape Hideaway" "2.50"  "Galligan, Mr M"    "Vaughan, Tim"  "2nd"
"2.00"  "Chelmsford City"   "Handicap Nursery"  "Class 6"   "Luna Wish" "2.75"  "Quinn, Jimmy"  "Margarson, G G"    "1st"
"2.35"  "Chelmsford City"   "Handicap Nursery"  "Class 4"   "Dandizette (IRE)"  "3.75"  "Coughlan, Laura"   "Nicholls, Adrian"  "5th"
"3.10"  "Chelmsford City"   "Handicap"  "Class 3"   "Emenem"    "5.00"  "Williams, Levi"    "Dow, S"    "3rd"
"3.45"  "Chelmsford City"   "Novices"   "Class 4"   "Strelka"   "3.25"  "Steward, Louis"    "Beckett, R M"  "2nd"
"4.20"  "Chelmsford City"   "Handicap"  "Class 5"   "Bayston Hill"  "7.00"  "Marsh, Finley" "Usher, M D I"  "2nd"
"4.20"  "Chelmsford City"   "Handicap"  "Class 5"   "Dangerous Ends"    "6.00"  "Carver, William"   "Johnson, B R"  "9th"
"4.50"  "Chelmsford City"   "Handicap"  "Class 4"   "Attainment"    "3.00"  "Haynes, Joey"  "Tate, James"   "1st"
"5.25"  "Chelmsford City"   "Handicap"  "Class 6"   "Magicinthemaking (USA)"    "5.00"  "ONeill, K T"   "Long, J E" "2nd"

Solution

  • I would ditch the conversion table in favor of a little date arithmetic:

    $today = Get-Date -Format "dd/MM/yyyy"
    
    foreach ($file in $infiles) { 
        $folder = Split-Path $file -Parent
        $name = [System.IO.Path]::GetFileNameWithoutExtension($file)
        $outfile = Join-Path $folder "$name.csv"
    
        $csv = Import-Csv $file -delimiter "`t" | Select-Object @{n='Date';e={$today}},RaceTime,Track,Horse
    
        foreach ($row in $csv) {
            $row.Horse = ($row.Horse -split ' \(')[0]
            $row.Track = ($row.Track -split ' \(')[0]
            $RaceTime = Get-Date ($row.RaceTime -replace '\.',':')  # Get-Date expects a colon
            if ($RaceTime.Hour -lt 11) { $RaceTime = $RaceTime.AddHours(12) }
            $row.RaceTime = Get-Date $RaceTime -Format "HH:mm"
        }
    
        $csv | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Set-Content $outfile 
    }
    

    You could also think about dropping the separate Date column in the result CSV and formatting RaceTime as a full date right-away.