Selecting items in CSV file using Date - powershell

I am trying to select items by date in a CSV file using PowerShell. The format in the CSV file for the date is 1/8/2018 10:04:00 AM. When I run this I get no data although I know that data exists.
$events = Import-Csv c:\normtest\server2_perf.csv | foreach {
New-Object PSObject -prop #{
Date = [DateTime]::Parse($_.Date);
CPULoad = $_.CPULoad;
MemLoad = $_.Memload
}
}
$events | Where { $_.Date -eq (Get-Date).AddDays(-4) }

As you have a time part to your date, this will only work for exactly 4 days from now (i.e. where time of day = right now).
Assuming this part works correctly: Date = [DateTime]::Parse($_.Date);, you can do this:
$start = (Get-Date).Date.AddDays(4)
$fin = $start.AddDays(1) # assuming 1 day window
$events |
Where {$_.Date -gt $start -and $_.Date -lt $fin}
Alternatively, you could treat the date field as string:
$events = Import-Csv c:\normtest\server2_perf.csv |
Where {$_.Date -like "$(Get-Date).AddDays(-4).ToString("M/d/yyyy"))*" }
Assuming your date format is "M/d/yyyy"

Related

Trying to extract specific text and merge output with existing output

I want to extract text from a .txt file. The way the file is layed out is in this format (below first block). Optimally, I would like for the powershell script to take the content of username and votecount and output them side by side. With an integer of 25>= add the letter D beside it. With the output adding itself to a pre-existing output file. Say this week is week 1. And testuser voted 25 times. They should have the output "testuser" 25D. But say in week 2 they voted 24 times. Then it should be "testuser" 49D. However say they had 25 again. Output should then be "testuser" 50DD or 50D2?.. I have what I think should work as an initial baseline for the script which in itself doesn't work.. But combining an output with a pre existing output is beyond my capability. This needs to parse an entire txt file of some 100+ people. So imagine there's like an extra 100 users..
{
"username": "testuser",
"votecount": "42",
"votesclaimed": "0",
"lastvotetime": "2022-11-04 09:08:29",
"steamid": "00000000000000000000"
}
Below is what I am working with.
Get-Content -Raw C:\Users\--------\Desktop\votes.txt |
ConvertFrom-txt |
ForEach-Object {
[pscustomobject] #{
UserName = $_.username
VoteCount = '{0}{1}' -f $_.votecount, ('', 'D')[[int] $_.votecount -gt 25]
}
} |
Export-Csv -NoTypeInformation -Encoding utf8 C:\Users\---------\Desktop\outvotes.csv
Try following :
$match = Select-String -Path "c:\temp\test.txt" -Pattern '^\s*"(?<key>[^"]+)"\s*:\s*"(?<value>[^"]+)'
$table = [System.Collections.ArrayList]::new()
foreach( $row in $match.Matches )
{
$key = $row.Groups["key"].Value
$value = $row.Groups["value"].Value
if($key -eq "username") {
$newRow = New-Object -TypeName psobject
$table.Add($newRow) | Out-Null
}
$newRow | Add-Member -NotePropertyName $key -NotePropertyValue $value
}
$table | Format-Table
$groups = $table | Group-Object {$_.username}

PowerShell Object comparison issues

I am writing a PowerShell script that reads a calendar file in the following format:
date
20220914
20221014
20221114
20221214
20230116
I want to find the last date from that calendar before a date (normally today's date) and based on that generate a list of file names from that date +1 day up to today's date, the script below was working up to the moment that I have added 2023 calendar dates to the calendar file, not sure how to address the comparison issue between the date from the calendar file date object, find the script below for reference:
$fileNamePrefix = "Daily_File_"
$filesToProcess = ""
$fileType = ".csv"
$fileDate = "20221018"
# Import calendar
$calendarDates = Get-Content -path "C:\Users\me\CutOff_Clndr.txt" | Select-Object -Skip 1
#Reduce calendar entries to contain dates previous to FILE_DATE
$calendarDates = $calendarDates | where-object{ $_.date -lt $fileDate }
#Get Last entry before FILE_DATE
$calendarDates = $calendarDates | Sort-Object -Property date -Descending | Select-Object -First 1
#Convert calendar entries to date object for date calculations
$calendarDates = [datetime]::ParseExact($calendarDates, "yyyyMMdd", $null)
#Convert FLE_DATE date object for date calculations
$fileDate = [datetime]::ParseExact($fileDate, "yyyyMMdd", $null)
#Generate file list
for ($i = $calendarDates.AddDays(1); $i -le $fileDate; $i = $i.AddDays(1)) {
if ($filesToProcess)
{
$filesToProcess += '","' + $fileNamePrefix + $i.ToString("yyyyMMdd") + $fileType
$i.ToString("yyyyMMdd")
}
else
{
$filesToProcess += $fileNamePrefix + $i.ToString("yyyyMMdd") + $fileType
}
}
Write-Host $filesToProcess
Any help/suggestion addressing the conversion from the date object gathered from the calendar file or a different approach to this would be welcome.
Thanks

Edit csv column

I have a csv with 3 columns.
Date Time Event
12/19/2021 3:00pm Low
12/19/2021 1:30pm Low
12/20/2021 3:00pm Low
I'm trying to subtract 5 hours from each row.
How can I keep each object in a datetime format?
$time0 = Import-Csv $Tempdest | Select 'Time'
$timeEst = $time0 | ForEach-Object {
Write-Host $_.
([datetime]$_).AddHours(-5)
}
By looking at the provided screenshot this should work, it would be updating the imported CSV in memory. If it doesn't work it's best if you can share with us the CSV as plain text.
$csv = Import-Csv path/to/csv.csv
$csv | ForEach-Object {
$date = '{0} {1}' -f $_.Date, $_.Time -as [datetime]
$date = $date.AddHours(-5)
$_.Date = $date.ToShortDateString()
$_.Time = $date.ToShortTimeString()
}
$csv | Format-Table

Datetime in PowerShell can't convert my Time

I'm writing a Script to compare two sets of timevalues and then calculate a exact time.
My problem is the calculation with timestamps. I import the times from a .csv-file. The times look like this:
08:37;
11:47;
12:11;
17:34;
etc.
I made a variable for the times so i always have the correct time from the correct line from the csv file.
My goal ist to calculate the time from one timestamp to another like this: 11:47 - 08:37 = 3:10
If i do this in my PowerShell Script an error occurs: The value "time=12:39" can not be converted to type "System.DateTime". Error: "The string was not recognized as a DateTime. An unknown word starts at index 1"
Is datetime wrong in this case? How can i make this work?
Thx for your help.
If this has to do with your previous question and the CSV actually looks like this:
name;prename;date;time
Gantz;Mario;09.02.;07:37
Gantz;Mario;09.02.;11:23
Gantz;Mario;09.02.;12:34
Gantz;Mario;09.02.;17:03
Then this should do it
# create two variables to hold the times parsed from the CSV, Initialize to $null
$current, $previous = $null
# load the csv and loop through the records
$result = Import-Csv -Path 'D:\Test\times.csv' -Delimiter ';' | ForEach-Object {
$current = [datetime]::ParseExact($_.time, 'HH:mm', $null)
if (!$previous) { $previous = $current }
# subtracting two DateTime objects results in a TimeStamp
$elapsed = $current - $previous
$previous = $current
# output the record with column 'elapsed' appended
$_ | Select-Object *, #{Name = 'elapsed'; Expression = {$elapsed.ToString()}}
}
# output on screen
$result | Format-Table -AutoSize
# output to new CSV file
$result | Export-Csv -Path 'D:\Test\times_and_intervals.csv' -Delimiter ';' -NoTypeInformation
Output on screen:
name prename date time elapsed
---- ------- ---- ---- -------
Gantz Mario 09.02. 07:37 00:00:00
Gantz Mario 09.02. 11:23 03:46:00
Gantz Mario 09.02. 12:34 01:11:00
Gantz Mario 09.02. 17:03 04:29:00
Now that I see you also have a 'date' column in there, you should include that in the conversion to [datetime] aswell:
# create two variables to hold the times parsed from the CSV, Initialize to $null
$current, $previous = $null
# load the csv and loop through the records
$result = Import-Csv -Path 'D:\Test\times.csv' -Delimiter ';' | ForEach-Object {
$completeDate = '{0}{1} {2}' -f $_.date, (Get-Date).Year, $_.time
$current = [datetime]::ParseExact($completeDate, 'dd.MM.yyyy HH:mm', $null)
if (!$previous) { $previous = $current }
# subtracting two DateTime objects results in a TimeStamp
$elapsed = $current - $previous
$previous = $current
# output the record with column 'elapsed' appended
$_ | Select-Object *, #{Name = 'elapsed'; Expression = {$elapsed.ToString()}}
}
# output on screen
$result | Format-Table -AutoSize
# output to new CSV file
$result | Export-Csv -Path 'D:\Test\times_and_intervals.csv' -Delimiter ';' -NoTypeInformation
You are getting the error because you are not specifying the values that you are importing as [datetime]
I have replicated the error where I just specified 2 time values and subtracted them:
$st = "08:37" $et = "11:47" $di = $st - $et Cannot convert value
"08:37" to type "System.Int32". Error: "Input string was not in a
correct format."
Solution:
Specify the values of each entry like so:
[datetime]$starttime = "08:37"
[datetime]$endtime = "11:47"
$diff = $endtime - $starttime
If you just want the time in minutes etc. you can enter $diff.Minutes respectively
Hope this works for you.

Add a calculated field to an imported csv based on datetime

Could someone please assist with this one.
My current code imports a csv file which has three columns, so far it will update the column names to be more readable. I need to add a fourth column which is a calculated field based on a datetime field.
So need to check the datetime field then display a number of days before it is 90 days old.
e.g. "Today's date" - "03/03/2020 8:00:00 AM" = 31 days
90 days - 31 days = 59 days (the 59 days is to go into the calculated field column
Bit of a newb with powershell and have all other functions working, but this is what I'm left with and need to add it into the below call, when the csv is imported, header columns updated then exported to a new file.
$input = "C:\Data\test\unchanged101.csv"
$output = "C:\Data\test\unchanged101conv.csv"
$checkDate = (Get-Date).AddDays(-90)
$data = Import-Csv $input |
Where-Object {
($_."pwdlastset" -as [DateTime]) -lt $CheckDate
}
$headerConversion = #(
#{ Name = 'User account'; Expression = { $_.'cn' } }
#{ Name = 'Last modified date'; Expression = { $_.'pwdlastset' } }
#{ Name = 'Email address'; Expression = { $_.'mail' } }
)
(Import-Csv -Path $input) |
Select-Object -Property $headerConversion | Select-Object *,"Days Left" |
Export-Csv -Path $output -NoTypeInformation
The new column is the "Days Left" where I need to display the number of days left until it is 90 days old. How to I get the result from the code here, into that column for each row?
$checkDate = (Get-Date).AddDays(-90)
$data = Import-Csv $input |
Where-Object {
($_."pwdlastset" -as [DateTime]) -lt $CheckDate
}
Been working on this one for the past few days and just cant figure the last part out.
First of all, you should not use variable name $input as this is an Automatic variable
If you subtract one datetime object from another, the result is a TimeSpan object which has a property called Days you could use
$inputFile = "C:\Data\test\unchanged101.csv"
$outputFile = "C:\Data\test\unchanged101conv.csv"
$checkDate = (Get-Date).AddDays(-90).Date # .Date sets this to midnight
$result = Import-Csv $inputFile |
Where-Object { [DateTime]$_.pwdlastset -lt $CheckDate } |
Select-Object #{ Name = 'User account'; Expression = { $_.cn } },
#{ Name = 'Last modified date'; Expression = { $_.pwdlastset } },
#{ Name = 'Email address'; Expression = { $_.mail } },
#{ Name = 'Days Left'; Expression = { ($checkDate - [DateTime]$_.pwdlastset).Days } }
# output on screen
$result | Format-Table -AutoSize
# output to csv
$result | Export-Csv -Path $outputFile -NoTypeInformation
I would first add the new column and then go trough all the lines (with a foreach loop) check the remaining days and write them to the new "Days Left" column.
Note: I omitted your header conversion here. You need to run it first and then the "Days Left" code...
$data = Import-Csv $input #import everything
foreach($line in $data){
$daysLeft = 0
$daysSinceLastSet = ((Get-Date) - [DateTime]$line.pwdlastset).Days
if ($daysSinceLastSet -lt 90){
$daysLeft = 90-$daysSinceLastSet
}
$line."Days Left" = $daysLeft
}
$data | Export-Csv -Path $output -NoTypeInformation