Is there a way to grab Outlook calendar start times for recurring events in Powershell? - 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..
}

Related

IF between two times 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.
==============================

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"

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
}

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);

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?