To compare the day , date , timestamp of two lines in file and output the latest day,date,timestamp - powershell

I have below lines from two different file having day , date ,timestamp. I need to output the line with latest timestamp.
The lines of one file :
Tue 31/12/2000 17:13:29.83 - file copied
And another file content is :
Sun 17/07/1996 12:11:14.84 - drivers updated
The output must be
Tue 31/12/2000 17:13:29.83 - file copied
How can we compare timestamp?

To parse out the date from these strings you can do:
# get the date and time from the string, remove the dayname as it is incorrect for that date
$dateString = ("Sun 31/12/2000 17:13:29.83 - file copied" -split '-')[0].Substring(4).Trim()
$date1 = [datetime]::ParseExact($dateString, 'dd/MM/yyyy HH:mm:ss.ff', [CultureInfo]"en-US")
# do the same for the date in the second file and call that $date2
Then simply compare the dates using
$theDateYouWant = if ($date1 -gt $date2) { $date1 } else { $date2 }
By stripping off the dayname, you can use $null or [cultureinfo]::InvariantCulture instead of [CultureInfo]"en-US"

Related

Powershell string to unix time with correct timezone

I'm collecting a timestamp value and trying to transform it to a Unix format.
To do that, I'm using ParseExact method, like so:
$FILETIME = "20220709101112"
$EPOCHTIME = [datetime]::ParseExact($FILETIME,"yyyyMMddHHmmss",$null) | Get-Date -UFormat "%s"
echo $EPOCHTIME
1657361472
Get-Date transforms the timestamp to Unix format correctly, but there's an issue.
The returned value uses the local timezone (UTC-3), not UTC-0.
Therefore, in another system that value might be displayed with the wrong timezone.
I've tried to add 3 hours, but it appended the number instead.
$EPOCHTIME = $EPOCHTIME + 10800
echo $EPOCHTIME
165736147210800
How can I convert that timestamp correctly?
Ok, so here's one way to do it (borrowing from https://stackoverflow.com/a/246529/3156906).
The key is to find the TimeZoneInfo for the timezone the $FILETIME string is local to, and use that to convert the local time to UTC before converting to a Unix epoch timestamp.
# datetime string that is local to UTC-3,
# (equivalent to "2022-07-09 13:11:12 UTC")
$FILETIME = "20220709101112";
# because there's no timezone component in the custom
# format string (e.g. "z" or "zz") this gets converted
# to a datetime with "Kind = DateTimeKind.Unspecified"
# (see https://learn.microsoft.com/en-us/dotnet/api/system.datetime.parseexact?view=net-6.0#system-datetime-parseexact(system-string-system-string-system-iformatprovider))
$TIMESTAMP = [datetime]::ParseExact($FILETIME, "yyyyMMddHHmmss", $null);
# DateTime : 09 July 2022 10:11:12
# Kind : Unspecified
# get a reference to the timezone the original date
# string is stored local to. I guessed this by looking
# at the results of "[TimeZoneInfo]::GetSystemTimeZones()"
# and taking a timezone with -3:00 from UTC and no daylight savings
# but maybe there's a better match for your source data
$tz = [TimeZoneInfo]::FindSystemTimeZoneById("SA Eastern Standard Time");
# Id : SA Eastern Standard Time
# DisplayName : (UTC-03:00) Cayenne, Fortaleza
# StandardName : SA Eastern Standard Time
# DaylightName : SA Eastern Summer Time
# BaseUtcOffset : -03:00:00
# SupportsDaylightSavingTime : False
# this is the magic bit - treat $TIMESTAMP as a local time in
# timezone $tz, and convert it to UTC using the BaseUtcOffset
# and daylight saving rules for $tz
$UTCTIME = [TimeZoneInfo]::ConvertTimeToUtc($TIMESTAMP, $tz);
# DateTime : 09 July 2022 13:11:12
# Kind : Utc
# now convert it to a unix epoch timestamp
$EPOCHTIME = $UTCTIME | Get-Date -UFormat "%s";
# 1657372272
Bonus Round
You get the Unix epoch timestamp 1657361472 because the current timezone on the computer where you're running your script is UTC, which is 3 hours offset from the timezone the string is local to.
Notes on DateTime.ParseExact Method
If s does not represent a time in a particular time zone and the parse
operation succeeds, the Kind property of the returned DateTime value is
DateTimeKind.Unspecified. If s does represent the time in a particular time
zone and format allows time zone information to be present (for example, if
format is equal to the "o", "r", or "u" standard format specifiers, or if it
contains the "z", "zz", or "zzz" custom format specifiers), the Kind
property of the returned DateTime value is DateTimeKind.Local.
This question has been answered in this post:
Get formatted universal date / time
Essentially, it depends on the version of PowerShell that you're using. If it's Powershell 7.1+, then you can do:
Get-Date -AsUTC -UFormat "%s"
Otherwise, if it's a lower version, you need to use
Get-Date ([datetime]::UtcNow) -UFormat "%s"

How to convert powershell UTC datetime object to EST

I have date time strings coming in, formatted like the following:
2017-08-03T12:30:00.000Z
I need to be able to convert these to EST. Every function I have tried throws one error or another, typically being:
"String was not recognized as a valid DateTime."
I have tried variations of the below:
$time = '2017-08-03T12:30:00.000Z'
[datetime]$datetime = $time
$culture = [Globalization.CultureInfo]::InvariantCulture
[DateTime]::ParseExact($datetime, 'MM-dd-yyyy HH:mm:ss', $culture)
I think it has something to do with how the Date Time string I am referencing has the **T** and then the UTC time, but can't figure out what to do about it. Maybe I should parse out the time, convert it and then reattach to the first part of the string, the date, and combine them together for the final output? Seems like way too much work and a solution which would cause potential errors in the future.
You should be able to convert a Zulu time string to a DateTime value simply by casting it. However, the resulting value will be in local time, so you should convert it back to UTC for further calculations:
$timestamp = '2017-08-03T12:30:00.000Z'
$datetime = ([DateTime]$timestamp).ToUniversalTime()
Then you can use the TimeZoneInfo class to convert the UTC timestamp to the desired timezone:
[TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($datetime, 'Eastern Standard Time')
Use [TimeZoneInfo]::GetSystemTimeZones() | Select-Object Id, DisplayName to get a list of the recognized timezones.
Try using the static ConvertTimeBySystemTimeZoneId() method of the [System.TimeZoneInfo] class:
$time = '2017-08-03T12:30:00.000Z'
$result = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId((Get-Date -Date $time), 'Eastern Standard Time')
The returned $result is a [DateTime].
BTW, if you ever need to convert it back, here's how:
Get-Date -Date $result -Format FileDateTimeUniversal
Hope this helps.

Get last monday date

I want to get the last Monday date for the given date. For example If my input is 190113 I want the output as 190107 which is last Monday.
if {$current_date == "Mon"} {
set startday [clock seconds]
set startday [clock format $startday -format %y%m%d]
puts $startday
} else {
puts "no monday today"
#I don't know how to get last monday date
}
This can be done fairly simply, by taking advantage of the fact that clock scan has quite a complex parser, and you can supply a timestamp that everything is relative to via the -base option. Also, both clock scan and clock format take -format options so that you can specify exactly what is going on in your input and output data.
proc getLastMonday {baseDate} {
set base [clock scan $baseDate -format "%y%m%d"]
set timestamp [clock scan "12:00 last monday" -base $base]
return [clock format $timestamp -format "%y%m%d"]
# This would work as a one-liner, provided you like long lines
}
Demonstrating:
puts [getLastMonday 190113]; # ==> 190107
puts [getLastMonday 190131]; # ==> 190128
Reference: https://www.tcl.tk/man/tcl/TclCmd/clock.htm#M22
Here's a sample code-snippet for the purpose. Added inline comments for understanding:
proc get_last_monday_date {date} {
# Get the end timestamp for the specified date
set end_timestamp [clock scan ${date}-23:59:59 -format %y%m%d-%H:%M:%S]
# Get day of the week for the current date
set day_of_week [clock format $end_timestamp -format %u]
# Sunday may report as 0 or 7. If 0, change to 7
# if {$day_of_week == 0} {
# set day_of_week 7
# }
# Monday is 1st day of the week. Monday = 1.
# Find how many days to go back in time
set delta_days [expr $day_of_week - 1]
# Multiply the delta by 24 hours and subtract from end of the day timestamp
# Get the timestamp for the result. That's last Monday's timestamp.
return [clock format [clock add $end_timestamp -[expr $delta_days * 24] hours] -format %D]
}
puts "Last Monday for 01-Jan-2019: [get_last_monday_date 190101]"
puts "Last Monday for 06-Jan-2019: [get_last_monday_date 190106]"
puts "Last Monday for 15-Jan-2019: [get_last_monday_date 190115]"
puts "Last Monday for 31-Jan-2019: [get_last_monday_date 190131]"
Execution output:
Last Monday for 01-Jan-2019: 12/31/2018
Last Monday for 06-Jan-2019: 12/31/2018
Last Monday for 15-Jan-2019: 01/14/2019
Last Monday for 31-Jan-2019: 01/28/2019

how to compare two custom dates in powershell v2.0

Is it possible to compare 2 custom dates. Am trying check if variables hold date1 is lessthan date2, if so, report saying date1 is older date.
I getting both dates from a. date1 from log file and date2 from application itself
now, both date1 and date2 are in required format ie,
$Date1 = Tue,Aug 16, 2016 12:40:03
$Date2 = Mon,Aug 22, 2016 16:33:02
my next step is compare these 2 dates and report if date1 is older date compare to Date2, which I don't know how to proceed.. Any help/ideas is much appreciated.
Thanks to Pete and Ansgar Wiechers
updated working Code :
$Date1DateTime = [DateTime]::ParseExact($Date1,'ddd,MMM d, yyyy, HH:mm:ss',[Globalization.CultureInfo]::InvariantCulture); $Date2DateTime = [DateTime]::ParseExact($Date2,'ddd,MMM d, yyyy, HH:mm:ss',[Globalization.CultureInfo]::InvariantCulture); $Date1DateTime -lt $Date2DateTime
You can only compare date strings if the string sort order is the same as the date sort order. For instance, date strings in ISO format are comparable:
2016-08-16T12:40:03
2016-08-22T16:33:02
Date strings in your custom format are not, because T comes after M, but August 16 should actually come before August 22:
Tue,Aug 16, 2016 12:40:03
Mon,Aug 22, 2016 16:33:02
If you don't have the date strings in ISO format it's usually better to parse them into actual DateTime values (as #PetSerAl suggested), particularly if your reference value is originally a DateTime anyway.
$fmt = 'ddd,MMM d, yyyy, HH:mm:ss'
$culture = [Globalization.CultureInfo]::InvariantCulture
$Date1 = Get-Date $LogFileDate
$val = (b2b.exe -readparams $param | Select-Object -Skip 1 -First 1) -split '='
$Date2 = [DateTime]::ParseExact($val[1], $fmt, $culture)
if ($Date1 -lt $Date2) {
...
}

Powershell variable interrogation of date & time difference

Morning All,
I have a variable as follows: $machines = $user2,$name,$serial,$purchased
sample data stored in $machines is:
User1,
Laptop1,
xyz1234,
01/01/2010
I am wanting to create a new variable called $tobereplaced containing all of the records in $machines with a date greater than 4 years old from todays date.
the fuzzy logic code for this im expecting to be someting like $tobereplaced = $machines.$purchased | where {$_$purchased = -getdate > 4 years} etc etc but i cant quite figure it out.
Assistance would be greatly appreciated.
Thanks
$fourYearsAgo = (Get-Date).AddYears(-4)
$tobereplaced = $machines | Where-Object { (Get-Date $_[-1]) -le $fourYearsAgo }
Convert the date as DateTime and compare it against a date four years ago. Like so,
# Assuming $m[3] contains the timestamp, parse it as a DateTime and compare
# against a date four years ago.
if([DateTime]::Parse($m[3]) -le [DateTime]::Now.AddYear(-4)) {
$tobereplaced += $m
}
Depending on your locale, you might need to tell [DateTime]::Parse() how to parse the date. Is 01/12/2010 1st of December, 2010 or 12th January, 2010?