How to check if a user passed date is Wednesday using PowerShell? - powershell

I have an use case where user passes a date from the past. But I need to check if it's a Wednesday. If not, I want to be able to set it to next Wednesday 5 AM. Can somebody please tell me what would be best approach to go about this using PS?
Thanks.

Fortunately [datetime] structs have a DayOfWeek property we can use to check that!
Simply advance the date by 1 day at a time until you reach Wednesday:
function Get-UpcomingWednesdayAt5
{
param(
[datetime]$Date
)
while($Date.DayOfWeek -ne [System.DayOfWeek]::Wednesday){
# advance 1 day at a time until its wednesday
$Date = $Date.AddDays(1)
}
# Create new [datetime] object with same Date but Time set to 5AM
return Get-Date -Date $Date -Hour 5
}

Related

Is there a way to grab Outlook calendar start times for recurring events in Powershell?

In Powershell, I am trying to get start times of calendar entries from my Outlook - this works fine except for recurring appointment, the date populated appears to be from when the recurring event was initially created. Is there a way to get the calendar date entry, as opposed to when the recurring event was first entered in? I may be using the incorrect property;
$outlook = New-Object -ComObject outlook.application
$namespace = $outlook.GetNameSpace('MAPI')
$Calendar = [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderCalendar
$folder = $namespace.getDefaultFolder($Calendar).items
#$folder.IncludeRecurrences = $True
$StartWeek = '02/12/2019'
$StartWeekDT = [datetime]::ParseExact($StartWeek,'dd/MM/yyyy', [cultureinfo]::InvariantCulture)
$EndWeekDT = $StartWeekDT.AddDays(5)
$Start = $StartWeekDT.ToString('dd/MM/yyyy') + " 00:00"
$End = $EndWeekDT.ToString('dd/MM/yyyy') + " 00:00"
$Filter = "[Start]>= '$Start' AND [End] <= '$End'"
$data = $Folder.Restrict($filter) | Select-Object
So here you can see that the filter says that the start property must be greater than 02/12 - which does pick up the recurring event entry. However, when I attempt to view the start property, it shows a date from January (when it was created) instead. I cannot see the correct date in any of the properties, and I've tried setting IsRecurring to false (to see if it would recreate the entry with the correct start) and by using .IncludeRecurrences as suggested by a few online articles, but no luck. Has anyone had this issue before?
05/12/2019 10:30:00
05/12/2019 10:00:00
05/12/2019 15:00:00
02/12/2019 16:30:00
03/12/2019 11:00:00
04/12/2019 16:00:00
05/12/2019 15:30:00
05/12/2019 16:30:00
14/01/2019 08:30:00
11/01/2019 16:30:00
16/01/2019 12:00:00
Could not figure out how to get the 'just this occurrence' start property, so I just found the start value a different way by adding on 7 days (from the recurring start date) until it was within my search scope, then assigned this to the $entry.start variable - for further processing. Note that this does not amend the calendar entry, but just updates $entry.start to the value within the week after the property has already been pulled. I can then query to see if it was on a monday, tuesday, etc.
Foreach($Entry in $data){
IF ($Entry.Start -lt $EndWeekDT){
for($i = $Entry.Start; $i -le $EndWeekDT; $i = $i.AddDays(7))
{
$Entry.Start = $i
}
}
etc..
}

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

Using Powershell how do you get the weekday number?

Using a Powershell date object how do you get the day number of the week, 0 to 6 where 0 would be Sunday and 6 would be Saturday. I know that I can get the day name with the code below but how do I get the number as there is no DayNumberOfWeek or equivalent property?
(Get-Date).DayOfWeek
I suppose I could use the day name from the code above in a switch statement to convert it to a number but that doesn't seem to be very eloquent.
like this:
( get-date ).DayOfWeek.value__
I suggest for the future to investigate what properties an object in this way:
( get-date ).DayOfWeek | gm -f # gm is an alias for get-member
Well, the DayOfWeek property of a DateTime is not a string but rather a DayOfWeek enum, so the shortest answer is probably
[Int] (Get-Date).DayOfWeek # returns 0 through 6 for current day of week
Or
[Int] [DayOfWeek] "Wednesday" # returns 3
Get-Date -UFormat %u
will return formated date.
check http://technet.microsoft.com/en-us/library/hh849887.aspx for more fomats
On Friday the 17th:
(get-date).DayOfWeek.value__
Returns 5
(Get-Date).DayOfWeek
Returns Friday
(Get-Date).Day
Returns 17

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?