Change time of a single cell in CSV using powershell - powershell

I have a .CSV file and i need to modify a single cell by changing only the Time format of the last row.
Import-Csv .\logs.csv | select -Last 1
will output the last row
Date : 2019-07-31 02:15 GMT
ID : 1252321
I need to modify the time from the date column from GMT to GMT+8 (military format) on the same .csv file.
Expected Result would be
2019-07-31 10:15:00

You could potentially do something like the following, which relies on the ConvertTime method in the TimezoneInfo class. I chose W. Australia Standard Time as the UTC+8 time zone. You can choose something more appropriate. The [-1] index grabs the last row of the CSV contents $csv.
$csv = Import-Csv .\logs.csv
$csv[-1].date = Get-Date ([System.TimeZoneInfo]::ConvertTime([datetime]($csv[-1].date),([System.TimeZoneInfo]::FindSystemTimeZoneById('W. Australia Standard Time')))) -Format 'yyyy-MM-dd HH:mm "GMT"+8'
$csv | Export-Csv .\logs.csv -NoType
You can remove the GMT+8 part if you feel it is not necessary. An easier alternative is to just add X number of hours based on your current system's time zone to the selected time. If you are already in GMT, you can just add 8 hours.
Get-Date [datetime]($csv[-1].date).AddHours(8) -Format 'yyyy-MM-dd HH:mm'

Related

Powershell Script to archive files over 1 day

I am looking for a script that can ignore the timing and utilise just the date to move files after 1 day, so yesterday, to an archive folder.
My knowledge of powershell is not great so any advice on how i can do this would be great.
Everyday i run a script that generates a .txt report which has a filename .....2022 01 02 (The filename ends with the date) so would like to add some extra lines that archives the .txts that were created yesterday to an archive folder.
The [datetime] type has a Date property that gives you the date at midnight, thereby allowing you to compare dates without taking the time component into account:
# Construct datetime value describing yesterday at midnight
$yesterday = (Get-Date).AddDays(-1).Date
# Filter files based on date of the `CreationTime` property
$filesCreatedYesterday = Get-ChildItem -Path .\path\to\folder -File |Where-Object { $_.CreationTime.Date -eq $yesterday }
$filesCreatedYesterday will now contain the files created yesterday

Trying to format ticks as datetime and export to excel

I am struggling a bit with an issue I hope you can help me with.
I am using get-winevent to grab specific events from a computer and export the results to a csv.
I am setting a variable to hold all of the returned events and then using a foreach loop to step through all the events and export them to a csv file.
When I export the timecreated object, the data is formatted as date-time and I can sort oldest to newest or newest to oldest. What I am running into is that the default format of "timecreated" is "MM/DD/YYYY hh:mm ". This causes a problem in that, unless I can see seconds and milliseconds, a lot of these events appear to happen at the same time.
To resolve this, I have been using the following to format the date:
$ticks = [datetime]$event.timecreated.Ticks
$date = $ticks.Tostring("MM/dd/yyyy hh:mm:ss:fff")
This works well when I just output to the screen, the date shows exactly like I want it to. However, since the variable is a string, when I export the variable to excel I can’t sort based on time.
Does anyone know of a way to convert ticks to the display format I want, but keep it as datetime rather than a string? Or any way to grab the timecreated object and format it the way I want, without having to convert it to a string?
I'm beginning to think I may have to create a PSObject and handle it that way, but I am not sure I can do it even then.
Thanks for reading.
if i understand your whole query and excepted result.
I have tested what your are looking for and result it to we doesn't have to add "fff" to string date format on excel because it's doesn't work.
Try this :
$ticks = [datetime]$event.timecreated.Ticks
$date = $ticks.Tostring("MM/dd/yyyy hh:mm:ss")
The full example we have using for testing :
$events =Get-WinEvent -ListLog * | Where {$_.IsClassicLog -eq ‘True’}
$events | Select-Object LogMode, RecordCount, LogName, #{n="DateWrite";e={$_.LastWriteTime.ToString("dd/MM/yyyy hh:mm:ss")}} | Export-Csv -Path c:\fso\event_tester.csv -Encoding ascii -NoTypeInformation
At result have the excepted Date column :
Resources :
How to represent a DateTime in Excel
pandas output timestamps to_excel with microseconds

Importing Data From CSV in Powershell Providing UK Date in CSV is Less Than 7 Days Away

so I've got a CSV file with 5 headings: name, collectionDate, location, equipmentNotes, manager.
Now my collectionDates are all in UK format so DD/MM/YYYY. I only want to import data from the CSV with collection dates that are 7 days or less in the future.
So today is 17/08, therefore I would only want to pull data from the CSV that is dated between 17/08 to 24/08.
Although Powershell sort of handles datetime objects in UK format if you tell it to, I seem to be unable to then manipulate the date to add on 7 days.
Here is my current code:
$today = Get-Date
$thisWeek = $today.AddDays(7)
$thisWeekString = $thisWeek.ToString()
$dateParts = $thisweekString -split " "
$weekFinal = $dateParts[0]
$import = Import-Csv #("\\location\EmailCSV.csv") | Where-Object {$_.collectionDate -lt $weekFinal}
Powershell correctly adds 7 days to the datetime to make it 24/08, and then when converting it to a string and removing the time from it, it correctly sets the variable as 24/08/2018. But when I then go to compare them in the Import cmdlet, it just returns all data in the CSV, rather than dates less than 24/08.
I also know Powershell can compare these, because if I create a separate variable $otherDate with 24/08/2018 in it, and then create an if statement that checks if $weekFinal is greater or less than $otherDate, it correctly runs the statement when true.
I've tried using both Where and Where-Object in the Import-Csv cmdlet, but both have returned the same results.
How do I get Powershell to correctly compare $_.collectionDate and $weekFinal to filter the imported data from the csv?
It is easiest to perform all calculations and comparisons using [datetime] instances - avoid string operations (except for converting a string representation of a date to a [datetime] instance).
First, express today's date and 1 week from now as a [datetime] instance without a time-of-day component:
$today = (Get-Date).Date # Today's date, without a time component (midnight)
$oneWeekFromToday = $today.AddDays(7)
Then use [datetime]::Parse() to convert the invariably string-typed CSV column value of interest to a [datetime] instance so you can perform proper date-comparison.
$import = Import-Csv \\location\EmailCSV.csv | Where-Object {
$thisDate = [datetime]::Parse($_.collectionDate)
# Process this row if its date falls between today and 1 week from now, inclusively.
$thisDate -ge $today -and $thisDate -le $oneWeekFromToday
}
Important: use [datetime]::Parse('...'), not a [datetime] '...' cast, because only [datetime]::Parse() respects the current culture's date and time formats; by design, PowerShell's casts and string interpolation always use the invariant culture, irrespective of the current culture - for more information, see this answer of mine.
Try casting the strings to [datetime] in your comparison. When using a sample set of data, I was able to get the expected results.
$import = Import-Csv #("\\location\EmailCSV.csv") | Where-Object {[datetime]$_.collectionDate -lt [datetime]$weekFinal}

Powershell Convert Date format in a CSV

I have a CSV file with the following data
"Date","Time","Name","SourceIP","DestinationIP"
"Sep 1","03:55:57","mmt-5","172.16.48.158","22.22.22.22"
"Sep 1","03:55:57","mmt-5","172.16.48.158","22.22.22.22"
"Sep 1","03:55:57","mmt-5","172.16.48.158","22.22.22.22"
"Sep 1","03:55:57","mmt-5","172.16.48.158","22.22.22.22"
I would like to convert the date into something more usable like 09-01-2016 (the year would be the current year).
How can I accomplish this?
That's easy using the [DateTime] class's ParseExact method. You supply the string that is a date, you tell it how the date is formatted, and you provide a culture or provider or something, but I always just use $null.
[datetime]::ParseExact("Sep 1","MMM d",$null)
That comes out to:
Thursday, September 1, 2016 12:00:00 AM
So you could just do something like:
$Array | ForEach{[datetime]::ParseExact($_.Date,"MMM d",$null)}
And that would convert each entry's Date property to a valid [datetime] object. Then you just format it however you want:
$Array | ForEach{[datetime]::ParseExact($_.Date,"MMM d",$null).ToString("M-d-yyyy")}
That would output:
9-1-2016
Or for the exact thing you asked for use "MM-dd-yyyy" to get 09-01-2016.
Edit: Thanks to wOxxOm for educating me about the third parameter's necessity when dealing with non-localized date formats! So, if this needs to be localized for other cultures, you will need to include that last parameter. That can be done as such:
$Culture = [cultureinfo]::GetCultureInfoByIetfLanguageTag('en-US')
$Array | ForEach{[datetime]::ParseExact($_.Date,"MMM d",$Culture).ToString("MM-dd-yyyy")}
Edit2: Ok, to replace your current Date field with this information you could pass the array to the Select command, and create a new Date property on the fly, and discard the original, then pass that to Export-CSV:
$Array | Select *,#{l='Date';e={[datetime]::ParseExact($_.Date,"MMM d",$null).ToString("M-d-yyyy")}} -Exclude Date | Export-CSV D-Sample-2.csv -NoType

Retrieving the full name of files, filtered by date

$date = [datetime]("05/19/2014")
gci -Recurse | Select-Object FullName,LastWriteTime | Where-Object { $_.LastWriteTime.ToShortDateString() -ge $date.ToShortDateString() } | Format-Table
I'm trying to find the list of files that have been altered on or after the 19th of May, 2014. Two things are happening here:
I'm getting files that have been altered from as far back as 2009
The table's columns are very wide, I'd say about 100 or so characters (I could be very wrong as I am eyeballing this)
How can I get the proper list of files and additionally, how can I sort them in such a manner as they are readable?
The issue may be in how you are doing your comparison. The DateTime.ToShortDateString method uses whatever the short date pattern for the current culture your process is using. Unfortunately, I can't think of an example that would make a date in 2009 appear to be greater than a date in 2014 in string form. Try just comparing the date-time object directly. You could just compare dates by using the Date property as such:
$date = [datetime]("05/19/2014")
gci -Recurse | Select-Object FullName,LastWriteTime | Where-Object { $_.LastWriteTime.Date -ge $date } | Format-Table -AutoSize
Note that I did not need to use the Date property on your $date variable, as when instantiating a DateTime object with only date information, the time is set to 12:00 AM. The Date property will provide a value with the date of the original DateTime object but with the time set to 12:00 AM.
The -AutoSize parameter I added to Format-Table will take care of your second question, as it will automatically resize columns to a sane width.