IF between two times powershell - powershell

I am trying to figure out if an issue happened during a certain period of time however for what ever reason nothing seems to be working.
Here is my powershell.ps1 file
$AUS_start = Get-Date -Hour 22 -Minute 00 -Second 00
$AUS_end = Get-Date -Hour 06 -Minute 00 -Second 00
$AS = $AUS_start.ToString("HH:mm:ss")
$AE = $AUS_end.ToString("HH:mm:ss")
foreach ($SHtime in $Rservices.start_time) {
$x = $SHtime.ToString("HH:mm:ss")
$x
if ($x -gt $AS -and $x -lt $AE) {
Write-Host "true"
}
else {
Write-Host "false"
}
}
Here is the response I get
22:18:01
false
19:11:00
false
05:15:00
false
05:15:00
false
02:36:43
false
As you can see, there are certain times for example "22:18:01" that definitely meet the criteria of greater than UTC 22:00:00 and less than 06:00:00 but it still returns a false value.
Any ideas?

this does what i think you want. [grin]
instead of testing for in 2200-0600 it tests for NOT in 0600-2200. that test is simpler since it gives one a continuous range that is all in one day. if you need to allow 2200-2259, you can simply shift the $EndHour to 21.
please note that this explicitly ignores the date and only uses the hour-of-day. if you need to look at the date, that will require some extra code. if i understand your intent, tho, that seems unlikely.
what the code does ...
creates a set of datetime objects to work with
when ready to work with real data, simply remove the entire #region/#endregion block and replace it with a call to your data source.
sets the start/end hours
builds the excluded hours range
iterates thru the collection of test datetime objects
checks to see if the .Hour of the current object is in the $ExcludedHours range
if yes, writes a warning to the screen to not disturb the "normal working hours" folks
if NO, writes a msg that it is safe to do IT work while the office folks are all far away
here's the code ...
#region >>> create some date time items to test with
# when ready to use real data, replace the entire "#region/#endregion" block with the real data source
$RServices = #(
[PSCustomObject]#{
Name = 'LastYearElevenP'
Start_Time = (Get-Date).Date.AddYears(-1).AddHours(23)
},
[PSCustomObject]#{
Name = 'LastMonthElevenP'
Start_Time = (Get-Date).Date.AddMonths(-1).AddHours(23)
},
[PSCustomObject]#{
Name = 'YesterdayElevenP'
Start_Time = (Get-Date).Date.AddDays(-1).AddHours(23)
},
[PSCustomObject]#{
Name = 'ZeroA'
Start_Time = (Get-Date).Date
},
[PSCustomObject]#{
Name = 'OneA'
Start_Time = (Get-Date).Date.AddHours(1)
},
[PSCustomObject]#{
Name = 'ThreeA'
Start_Time = (Get-Date).Date.AddHours(3)
},
[PSCustomObject]#{
Name = 'SixA'
Start_Time = (Get-Date).Date.AddHours(6)
},
[PSCustomObject]#{
Name = 'SevenA'
Start_Time = (Get-Date).Date.AddHours(7)
},
[PSCustomObject]#{
Name = 'NineA'
Start_Time = (Get-Date).Date.AddHours(9)
},
[PSCustomObject]#{
Name = 'ElevenP'
Start_Time = (Get-Date).Date.AddHours(23)
}
)
#endregion >>> create some date time items to test with
$StartHour = 6
$EndHour = 22
$ExcludedHours = $StartHour..$EndHour
foreach ($RS_Item in $RServices)
{
if ($RS_Item.Start_Time.Hour -in $ExcludedHours)
{
Write-Warning (' {0} is in the Excluded Hours ...' -f $RS_Item.Start_Time.ToString('yyyy-MM-dd HH:mm:ss'))
Write-Warning ' Do nothing disruptive at this time.'
}
else
{
'{0} is NOT in the excluded hour range.' -f $RS_Item.Start_Time.ToString('yyyy-MM-dd HH:mm:ss')
' Now is the time to do things that the office folks might complain about.'
}
'=' * 30
}
the screen output ...
2019-04-29 23:00:00 is NOT in the excluded hour range.
Now is the time to do things that the office folks might complain about.
==============================
2020-03-29 23:00:00 is NOT in the excluded hour range.
Now is the time to do things that the office folks might complain about.
==============================
2020-04-28 23:00:00 is NOT in the excluded hour range.
Now is the time to do things that the office folks might complain about.
==============================
2020-04-29 00:00:00 is NOT in the excluded hour range.
Now is the time to do things that the office folks might complain about.
==============================
2020-04-29 01:00:00 is NOT in the excluded hour range.
Now is the time to do things that the office folks might complain about.
==============================
2020-04-29 03:00:00 is NOT in the excluded hour range.
Now is the time to do things that the office folks might complain about.
==============================
WARNING: 2020-04-29 06:00:00 is in the Excluded Hours ...
WARNING: Do nothing disruptive at this time.
==============================
WARNING: 2020-04-29 07:00:00 is in the Excluded Hours ...
WARNING: Do nothing disruptive at this time.
==============================
WARNING: 2020-04-29 09:00:00 is in the Excluded Hours ...
WARNING: Do nothing disruptive at this time.
==============================
2020-04-29 23:00:00 is NOT in the excluded hour range.
Now is the time to do things that the office folks might complain about.
==============================

Related

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

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"

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 check if a user passed date is Wednesday using 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
}

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 Display Modified Time and Modified By Fields Correctly with Powershell

I have a script that outputs to CSV all items/files from all Lists and Libraries. In addition, it displays the current and previous versions of an item/file. This also displays which user modified the file for each version and also displays the date/time the file was modified for every version:
function Get-DocInventory([string]$siteUrl) {
$web = Get-SPWeb "http://contoso.com/sites/Depts3/HBG"
foreach ($list in $web.Lists) {
foreach ($item in $list.Items) {
foreach($version in $item.Versions){
$data = #{
"Version" = $version.VersionLabel
"List Name" = $list.Title
"Created By" = $item["Author"]
"Created Date" = ($item["Created"] -as [datetime]).DateTime
"Modified By" = $version["Editor"]
"Modified Date" = ($version["Modified"] -as [datetime]).DateTime
"Item Name" = $item.Name
}
New-Object PSObject -Property $data | Select "List Name", "Item Name", "Version", "Created By", "Created Date", "Modified By", "Modified Date"
}
}
$web.Dispose();
}
}
Get-DocInventory | Export-Csv -NoTypeInformation -Path C:\GenerateReport.csv
Below is a sample of what the script outputs:
And below is an excel example of what I see when I go to the Version History of the Lions.pdf file:
I have 2 problems:
The column Modified By is displaying email and domain username which is not required.
My script displays the column Modified Date as 5 hours ahead. The script output for Version 1 of Lions.pdf displays time as 11:23 AM. But when I go to Version History of Lions.pdf it says that Version 1 was modified at 6:23 AM. The time discrepancy is the same across the board as 5 hours ahead which is incorrect.
I can't seem to figure out what I am doing wrong here. Can someone please assist in the issue I am having? My main concern is the time and I would greatly appreciate any assistance.
User Fields
Normally in server side code, accessing a user field value using array notation (eg myItem["Author"]) would return an object that you would cast to an appropriate type (Microsoft.SharePoint.SPFieldUserValue). Powershell, however, automatically casts these values to strings, which is why you're getting undesirable values.
Fortunately, there's a way around it! First, get the field itself as an object, then pass the field value into the field's GetFieldValue() method.
$userField = $item.Fields.GetField("Author");
$authorObject = $userField.GetFieldValue($item["Author"]);
You'll then have an object with properties you can access to retrieve the desired values, such as LookupValue for the user's display name on the site.
$authorName = $authorObject.LookupValue;
Date Fields
Date fields are little easier, because Powershell will actually hand them over to you as DateTime objects.
To format a DateTime object, you can just call .ToString() and pass in a parameter indicating the desired format.
$data = #{
...
"Modified Date" = $item["Modified"].ToString("MM/dd/yyyy h:mm tt");
...
}
Time Discrepancy
This is most likely attributable to your local timezone. The times displayed on a SharePoint site via the browser are determined by your PC's timezone settings. The times actually saved to SharePoint's underlying database are determined by the server's timezone settings.
To reconcile them, you can use the DateTime object's .ToUniversalTime() method to get a corresponding DateTime object in UTC time (and optionally offset it as desired until it aligns with the local timezone and daylight savings adjustments).
Edit: I'm guessing you're in US Eastern time (UTC-5) and it's giving you results in UTC time (Universal Coordinated Time, which is 5 hours ahead of you except during daylight saving time). You should be able to offset the hours manually to account for this.
$localOffset = -5;
$modified = $version["Modified"] -as [datetime];
if($modified.IsDaylightSavingTime()){$localOffset += 1;}
$modifiedLocal = $modified.addHours(-$localOffset);