How to get retrieve relevant calendar events through Google Calendar API? - powershell

I have come this far with my script, which is simply supposed to retrieve the entries for a particular calendar for a specific time period (i.e. exactly what I see in the calendar).
#Powershell
ls (join-path $Script:scriptpath .\GDataCmdLet-master\Binaries\*.dll) | % {
[System.Reflection.Assembly]::LoadFile($_)
}
$service=new-object Google.GData.Calendar.CalendarService('Test')
$cred = New-Object Google.GData.Client.GDataCredentials('joe#gmail.com', '1234')
$service.credentials=$cred
$eventquery=new-object Google.GData.Calendar.EventQuery
$eventquery.uri='http://www.google.com/calendar/feeds/joe#gmail.com/private/full'
$eventquery.StartDate = (Get-Date -Date '2014-02-10')
$eventquery.EndDate = (get-date -date '2014-02-20')
$eventfeed=$service.query($eventquery)
The DLLs I got from https://github.com/robertj/GDataCmdLet
All events from the calendar have actually been removed (i.e. I don't see any in the webinterface), but I keep on getting these as a result.
Questions, an answer to either one would suffice:
Is there a flag in the results, which distinguishes deleted from non-deleted events?
Is there a way to retrieve only the non-deleted events in the first place? (the parameter ?showhidden=false on the query didn't help)
Thank you!
Sandro

Solved it! The following seems to work, not sure exactly why tough
ls (join-path $Script:scriptpath .\GDataCmdLet-master\Binaries\*.dll) | % {
[System.Reflection.Assembly]::LoadFile($_)
}
$service=new-object Google.GData.Calendar.CalendarService('Test')
$cred = New-Object Google.GData.Client.GDataCredentials('joe#gmail.com', '1234')
$service.credentials=$cred
$eventquery=new-object Google.GData.Calendar.EventQuery
$eventquery.uri='http://www.google.com/calendar/feeds/joe#gmail.com/private/basic'
#don't use StartDate and EndDate this way
#they just didn't have the expected effect
$eventquery.StartTime = (Get-Date -Date '2014-02-10')
$eventquery.EndTime = (get-date -date '2014-02-30')
#that does the trick to get the actual occurences, not just the events
#and it also removed the non-deleted ones
$eventquery.SingleEvents = $true
$eventfeed=$service.query($eventquery)
Now I don't know where to get the start and end times of the occurences from, but that is for another question to answer...

Related

PowerShell CSV file conversion errors due PC with different DateTime format that the input file

I’m using PowerShell with a script to convert a .CSV raw data file into more manageable data format with separate columns, a cleaner view etc. And because the source file with the raw data is in US date and time format (e.g. 11/23/21, 1:00 PM), then if the PC is in that same US format the conversion process runs perfectly as should with 0 errors. BUT, if the PC is in a different country date and time format, then PowerShell shows errors in red in the process.
When the PC is in other DateTime format I see the main error is:
"Parse" with "1" argument(s): "String was not recognized as a valid DateTime."
And the problem is the PC where this will be used is not in US format (only changed to US format for testing), so could someone here please help me to add to the conversion process the syntax or sentence/s to simply specify directly in the code a fixed format that keeps a static output format independently about the PC clock date and time format, and if one of the inputs into the file is “11/23/21, 1:00 PM” then to specify in the code you want the output in the format “dd-MMM-yyyy hh:mm” to have a result like “23-Nov-2021 01:00 PM”
The code section in the script used for the conversion is:
…
$data = $csvData | ? {$_ -match "\(DTRE"}
dtreFileData = New-Object System.Collections.Generic.List[PSCustomObject]
foreach ($item in $data)
{
$null = $item.Strategy -match "\(DTRE\|(.*)\)"
$v = $Matches[1] -split '\|'
$resultvalue = $v[0] | Convert-CurrencyStringToDecimal
$expectedvalue = $v[1] | Convert-CurrencyStringToDecimal
$dtreData = [PSCustomObject]#{
'DateTime' = ([datetime]::Parse($item.'Date/Time'))
'ResultValue' = [decimal]$resultvalue
'ExpectedValue' = [decimal]$expectedvalue
}
$null = $dtreFileData.Add($dtreData)
$null = $dtreAllData.Add($dtreData)
}
$dtreFileData | Export-Csv -Path (Join-Path (Split-Path -Path $f -Parent) ($outFile + '.csv')) -Force -NoTypeInformation -Encoding ASCII
…
Example of raw source data (in the CVS file are dozens of lines like the next one):
...(DTRE|49.0|48.2);...;11/23/21, 12:58 PM...;
...(DTRE|52.1|52.0);...;11/23/21, 1:00 PM...;
...
...
And the Output looks like:
I tried with DateTime examples in other posts from here (stackoverflow.com) to adjust the code to work in a PC without US date and time format and to get the DateTime format result described above. Examples like:
'DateTime' = ([datetime]::Parse($item.'yyyy-MM-dd:HH:mm:ss'))
'DateTime' = ([datetime]::ParseExact($item.'yyyy-MM-dd:HH:mm:ss'))
…
$culture = [Globalization.CultureInfo]::InvariantCulture
…
'DateTime' = ([datetime]::ParseExact($item.'yyyy-MM-dd:HH:mm:ss', $culture))
…
But with these examples PowerShell shows the error “Cannot bind argument to parameter 'InputObject' because it is null”
Update after the answer from #Seth:
When trying next modification of the code, with the PC system date format in “24-Nov-21” and leaving the rest as above:
…
$resultvalue = $v[0] | Convert-CurrencyStringToDecimal
$expectedvalue = $v[1] | Convert-CurrencyStringToDecimal
$cultureInfo= New-Object System.Globalization.CultureInfo("es-ES")
$dtreData = [PSCustomObject]#{
'DateTime' = ([System.DateTime]::Parse($item.'Date/Time', $cultureInfo))
'ResultValue' = [decimal]$resultvalue
'ExpectedValue' = [decimal]$expectedvalue
…
then, PowerShell shows the next errors:
As it has been explained it's a good idea to fix the CSV to have a better dateformat. An example would be ISO 8601 which can be used with Get-Date -Format "o".
That said Get-Date relies on C# stuff in the background. So you can use C# code to read that in a particular culture. As you know the origin culture this should work. Fixing the timestamp is still a better idea.
$cultureInfo= New-Object System.Globalization.CultureInfo("en-US")
$dateString = "11/23/21, 12:58 PM";
$dateTime = [System.DateTime]::Parse($dateString, $cultureInfo);
Get-Date -Format "o" $dateTime
With this example code you'd assign $dateString the value of $item.' Date/Time' and the result you likely want would be the result of Get-Date. So you'd assign $dtreData.'DateTime' the result of that Get-Date call. Alternatively it is possible to use the .NET DateTime Object to directly convert to a particular culture. For instance by calling $dateTime.ToString((New-Object System.Globalization.CultureInfo("en-ES"))). Though not all that useful you could also pass the format identifier to this method. This might be relevant if you want to avoid creating additional objects. A somewhat unnecessary call would be $dateTime.ToString("o", (New-Object System.Globalization.CultureInfo("en-ES"))) (as format o is the same in every culture).

Handling Date in Power-Shell JSON Object

I am trying to get user info based on LastLogondate from AD. I am converting final output in JSON format.
Here the small script to handle dates. Actually I am passing $PasswordAge as LastLogonDate of the user.
$PasswordAge = (Get-Date).AddDays(-60) # This is actually LastLogonDate from user info
$CurrentDate = (Get-Date)
#Write-Host $PasswordAge
try
{
$LastLogonDays = (New-TimeSpan -Start $PasswordAge -End $CurrentDate).Days
#Write-Host $LastLogonDays
}
catch{
$Message = $_.Exception.Message
}
$JSONOutput = #{"result"=$LastLogonDays;"error"=$Message} | ConvertTo-Json #-Compress
Write-Output $JSONOutput
Receiving below error if I use ConvertTo-Json and print output. Day difference is correct but every-time getting message in error
{
"error": "Cannot bind parameter \u0027Start\u0027 to the target. Exception setting \"Start\": \"Cannot convert null to type \"System.DateTime\".\"",
"result": 60
}
Thank for your help in advance.
New-TimeSpan sucks. I almost always get the same error. It's reported that the issue stems from a mismatch of the culture (language) settings on your OS, the format your OS is configured to use for dates and times, and the format the DateTime object is actually in. I live in the US, use the English language, and use our standard format for dates and I still have this problems with getting New-TimeSpan to function. I've long-since given up on getting this cmdlet to work consistently.
Fortunately there's an easy workaround; just subtract two datetimes to get a System.TimeSpan instead. Works every time.
$LastLogonDays = ( $CurrentDate - $PasswordAge ).Days

Powershell keep looping until condition is true then proceed

I have written a script that so far is able to check a file "latest.json" for the "created_at" object which shows the last date that a commit has occurred for software.
$websiteJson = Invoke-WebRequest "https://website/latest.json" | ConvertFrom-Json | select created_at
$todaysDate = Get-Date -Format "yyyy-MM-dd HH:mm"
if($websitejson.created_at | where {$_.created_at -eq $todaysDate}){
Write-Output "Today's date matches"
} else {
Write-Output "has not yet been updated"
}
How part of latest.json looks like
"created_at":"2020-03-23 17:32:48"
How do I change this to keep looping until the date pull from latest.json matches then proceed to next step (would download and install software). Also, since "created at" has "17:32:48" will this cause the date check to fail since the time does not match?
. I want it to keep checking if dates match.
Thank you!
Right now, I'm not going to bother converting dates to match to make sure they're the same format, but what you need for your specific questions is just a do until loop. I might update this to check the date formats if you supply an example layout of the returned JSON.
Do{
$websiteJson = Invoke-WebRequest "https://website/latest.json" | ConvertFrom-Json | select created_at
$todaysDate = Get-Date -Format "yyyy-MM-dd HH:mm"
if($websitejson.created_at | where {$_.created_at -eq $todaysDate}){
Write-Output "Today's date matches"
} else {
Write-Output "has not yet been updated"
}
start-sleep -s 60
}until($websiteJson -eq $todaysDate)
I believe this wont work right off the bat. You'll have to get the JSON date and $todaysDate to be the same format, then you can do this and it will work.
if you want to compare the date and/or time, use datetime objects instead of datetime strings. something like this ...
if you want to test for the actual time difference between two time objects ...
((Get-Date -Date '2020-03-23 18:11:22') - [datetime]'2020-03-23 17:32:48').TotalHours
# result = 0.642777777777778
you keep mentioning date as if you don't want the time, so this method would work for comparing the date parts of two timestamps ...
# the date at the time the code was run = 2020 April 03, Friday 4:30:34 PM
$Today = (Get-Date).Date
$Created_At = '2020-04-03 15:15:15'
$Today -eq ([datetime]$Created_At).Date
result = True

Use Get-Date "time" in an "if" statement PowerShell

$WshShell = New-Object -ComObject wscript.shell
$Time = (Get-Date).hour
$Time2 = Get-Date -DisplayHint Time
$Message ="Test for $Env:username at: " + $Time2
$fail = "ERROR:It is $Time2, which is past 12PM"
$PopUp = $WshShell.popup("$Message",0,"Task Scheduler Pop-up",1)
if ($Time2 > 12)
{
$PopUp = $wshShell.popup("$Message",0,"Task Scheduler Pop-up",1)
}
else {
$PopUp = $wshShell.popup("$fail",2,"Task Scheduler Pop-up",1)
}
Hi guys, I'm practicing a little bit of my PowerShell and have run across something I'm not quite sure how to Google for, or what method I need to use to get this to work correctly.
What I'm attempting to accomplish is have my box display only, the hour and minute like "12:31".
As you can see in the script I'm calling the
Hour, but I can't quite figure out how to have it display the time by itself the right way. I'm using the "Time" operator, but when you compare that in the "IF" statement, it doesn't recognize it as something it can compare itself to since it's not a real integer. I understand why, but I would like to be able to compare the .Hour to $Time2
I'm new to this and appreciate any help you can provide!
Thank you!
Don't think in terms of output strings before you actually need to.
> won't work for comparisons, you need to use -lt (less than) and -gt (greater than)
If you want to compare the time of two DateTime objects (regardless of the date), you can compare the TimeOfDay property:
$DateTimeNow = Get-Date
$DateTimeEarly = Get-Date -Hour 1 -Minute 5
if($DateTimeNow.TimeOfDay -lt $DateTimeEarly.TimeOfDay){
"It is very early right now!"
} else {
"It is at least past 01:05"
}
If you want to show the time in output, you have multiple options for formatting a DateTime string:
You can use the ToString() method with a formatting string:
PS C:\> (Get-Date).ToString('HH:mm')
20:41
The format operator -f:
PS C:\> '{0:HH:mm}' -f (Get-Date)
20:41
Or have Get-Date return a formatted string itself:
PS C:\> Get-Date -Format 'HH:mm'
20:41
If you want 12-hour style time, use hh:mm
If you need to display the time you could use one of several methods. Those would all convert the result to string. I think you need to save $time2 as just a [datetime] object. That way you can format it for display and use .Hour for comparison logic.
$Time2 = Get-Date
$Message ="Test for $Env:username at: " + $Time2.ToString("HH:mm")
$PopUp = $WshShell.popup("$Message",0,"Task Scheduler Pop-up",1)
if ($Time2.Hour -gt 12){
#Do Stuff
}
This logic would only work for 24hr time though. 1(pm) is less than 12 but later in the day. Which is what HH:mm represents.

loop to minus 15 days from the current date

I'm trying to figure out what would be the best way to call an exe that requires a date range parameter (ex: 20130801-20130815) and then loop it so it minuses 15 days and calls the exe with the new date range.
I thought of using a do until but i'm not sure how (new to powershell/programming) but I'm sure this is far from the right method :). I've just started to figure this out, so thanks in advance for any/all help.
do {
$startDate = (Get-Date).adddays(-34)
$requireddate = some date that is set ad-hoc
$startdate.ToString("yyyyMMdd")
#[datetime]::parseexact($startdate,"MMddyyyy",$null)
Call THE EXE at this point with the parameters $startdate and $enddate
$enddate = $startdate.AddDays(-15)
write-host $enddate.ToString("yyyyMMdd")
}
until ($enddate -eq $requireddate)
You can use a For loop to do what you're trying to achieve as well:
(I've split things out into Variables a bit as well as I find it helps when writing functions)
$requiredAddDays = 30
$requiredDate = (get-date).AddDays($requiredAddDays)
$startDate = (get-date).AddDays(-34)
$endAddDays = -15
for($i = $startDate; $i -lt $requiredDate; $i = $i.AddDays(1))
{
Write-Output "$($i.ToString("yyyyMMdd"))-$($i.AddDays($endAddDays).ToString("yyyyMMdd"))"
}
Using Write-Output means that whatever is returned is returned as an object (whereas Write-Host always returns a string). By returning an object it can be fed into the Pipeline (using the pipe |)
The $(code) syntax in my Write-Output means that whatever is inside of the brackets gets evaluated before returning the string (as an object).
You could go one further and make this a parameterised function if you'll be using it lots:
Function Get-DateRange
{
Param(
[datetime]$startDate,
[int]$endAddDays,
[datetime]$requiredDate
)
for($i = $startDate; $i -lt $requiredDate; $i = $i.AddDays(1))
{
Write-Output "$($i.ToString("yyyyMMdd"))-$($i.AddDays($endAddDays).ToString("yyyyMMdd"))"
}
}
Then you could call it (once it's loaded into your session) by running something like this:
Get-DateRange -startDate (get-Date).AddDays(-10) -endAddDays 15 -requiredDate (get-Date).AddDays(15)
P.S. If you would like to write functions it might be a good idea to try and keep to the typical Powershell Verbs if you can. Run get-verb | sort verb to see the whole list. :)
There's lots of ways. If you want to use a Powershell specific method (not do..until or while(){} ) then you could go with a pipeline:
0..15 | %{
$changingDate = $startdate.AddDays(-$_)
#do your work with the .exe & $changingDate
$changingDate
}