I am looking to get the current UTC time, add 2 hours to it, then format both in the UTC format, so I can store that data in an XML file. Ultimate goal is then to get current UTC time on another machine, that could be in another time zone, and compare to the incremented time. So I can conditionally do stuff if two hours hasn't passed.
What I have is this
$now = Get-Date
$enqueued = $now.ToUniversalTime().ToString('u')
$expires = $now.Addhours(2).ToUniversalTime().ToString('u')
Write-Host "Q: $enqueued"
Write-Host "E: $expires"
$enqueued is formatted correctly, but $expires is not. I get
Q: 2020-06-02 18:41:58Z
E: 06/02/2020 22:41:58
And I expect
Q: 2020-06-02 18:41:58Z
E: 2020-06-02 20:41:58Z
I tried swapping .Addhours(2) & .ToUniversalTime() but it still doesn't format at all.
Interestingly
$now = (Get-Date).Addhours(2).ToUniversalTime().ToString('u')
$now
works right. So it's not the adding of hours alone. It's more like, once it's a variable the ability to add hours AND format is lost. Does that make any sense?
I also tried moving the UTC part to the $now assignment, since it was duplicated before.
$now = (Get-Date).ToUniversalTime()
$enqueued = $now.ToString('u')
$expires = $now.Addhours(2).ToString('u')
Write-Host "Q: $enqueued"
Write-Host "E: $expires"
Same results, $expires won't format.
Related
I am working on a GUI-based Powershell tool to help users easily find out when their AD password is going to expire. Due to Covid restrictions, most users and not on-site and rely on VPN to connect to AD. A by-product of this is that many do not see the automatic pop-up in Windows to remind them of them to set a new password soon. Those that are on-site see the notification OK. It's a not a group-policy problem. The tool will be will be rolled-out in two different languages - one representing the 'mothership' (where is English is not normally spoken) and English for all other countries.
Some of the (mostly) Eastern European countries use a short date format that reads like 'd.M.yyyy.' - according to settings menu when one changes the 'Region' setting in Windows.
The tool calculates the difference between today and the expiry data and outputs the number of days to a text field. The actual expiry is display correctly in its own text field.
Some of the source code behind it all...
$thisUser = [Environment]::UserName
#make string
"net user " + $thisUser + " /domain"
#make cmd string
$fetch_net_user = "net user " + $thisUser + " /domain"
#execute command and store to variable
$net_user_data_array = Invoke-Expression $fetch_net_user
#Gets password expiry date (with header)
$password_expiry_with_header = $net_user_data_array[11]
#extracts only the date and assigns to new variable (the hours and minutes) can be ignored)
$password_expiry_as_string = $password_expiry_with_header.Split(' ')[-2]
# Home countries - works OK
try{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'dd.MM.yyyy', $null)
}
# Others - works OK
catch{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'dd/MM/yyyy', $null)
# where problem occurs
catch{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'd.M.yyyy.', $null)
}
finally{
#show GUI error window...
}
#fetch date... converted to yesterday to fix an off-by-one bug!
$today = Get-Date
$rightNow = $today.AddDays(-1)
#calc days left
$daysRemaining = (New-TimeSpan -Start $rightNow -End $password_expiry_as_dateTime).Day
# some other code follows, manipulating date values etc. Works with most date formats.
When executed the script will throw several errors.
The first is...
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
Others will follow such as
You cannot call a method on a null-valued expression.
As the difference between today and the expiry date cannot be calulated.
Is there any easy fix for this? I'd rather avoid having to write a long list of 'if' statments for each country/culture. Thanks!
I'm sure the code could be a little bit more elegant, and that will be addressed in a later version. Right now, getting it to work some of the more obscure date formats is my priority.
Something else that I should stress is that this tool works in a 'read only' capacity. No 'Set-Item' commands are used.
Regards,
WL
You have 2 problems:
Multiple date formats used interchangeably
Trailing dots on some strings
The first problem can be solved by passing multiple format strings to ParseExact() - it'll try each in order until it successfully parses the input string (or reaches the end of the list):
[datetime]::ParseExact($password_expiry_as_string, [string[]]#('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)
The second problem can be solved by trimming trailing dots:
[datetime]::ParseExact($password_expiry_as_string.TrimEnd('.'), [string[]]#('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)
I have a script that checks for certain logs between two times $startDate and $endDate using Search-UnifiedAuditLog where $startDate is found by checking a line in a .txt file and $endDate is the current time. I run this as shown below.
$startDate = Get-Content $logPath -Last 1
$startDate = [datetime]$startDate
$startDate = $startDate.AddHours(-1)
$endDate = (Get-Date)
This particular script is run every hour, so the time between $startDate and $endDate is two hours (due to the AddHours). If I check the value of these variables, they are indeed two hours apart. However, when I run the script, it goes through the previous 6 hours of logs. This makes me think it is assuming that $startDate is in UTC, and it is converting it to my time zone. Is this what it is doing, and if so, how can I get my script to only check for logs one hour before the time listed in my .txt document?
Turning my comment into an answer
You can check the .Kind property of the $startDate variable.
This property can be either Local, Utc or Unspecified. See DateTimeKind Enum.
In case of Unspecified, since .NET 2.0, "This instance of DateTime is assumed to be a UTC time, and the conversion is performed as if Kind were Utc." as stated in the docs
I'm passing a string that represents a date i.e. 20180625 to my Powershell script.
I'm then taking the string parameter, which is called $currentDate and formatting it as follows:
$date = [datetime]::ParseExact($currentDate,"yyyyMMdd",$null)
However, when I write the $date variable out it's displaying as 6/29/2018 12:00:00 AM.
I'm doing this because I need to get the day of the year for my script:
$dayofyear = ($date).dayofyear
Which works. I just expected the $date to be in the yyyyMMdd format. Just curious as to why this is happening.
The format parameter for ParseExact tells the parser what format the date you are giving it is in. The object you get back is a DateTime object not a string. To get the string in the format that you want, use the .ToString() method then give if the format that you want the string to be in.
As an example:
$currentDate = '20180629'
$date = [datetime]::ParseExact($currentDate,"yyyyMMdd",$null)
$dayOfYear = $date.DayOfYear
$date.ToString('yyyyMMdd')
$date is an object of type [datetime] which contains an exact measure of time in ticks. For instance, a timespan of 1 day would be 864000000000 ticks. Thus it is not possible to have $null values in a lesser field (864 ticks would only be a few milliseconds). $date prints to the console with a default formatting, which can be changed. However, since each field down to -Milliseconds is populated as 0, when that default format does contain fields such as -hours, they will be displayed as the minimum value (in this case, 12am exactly).
I am trying to perform date-time comparison.
Datetime in log file- Tue Aug 4 17:05:41 2015
Local system date time from get-date command -
6. elokuuta 2015 10:18:47
It's 6 Aug 2015 10:18:47 after I translated it on Google Translate.
How do I convert this date/time format, so I can perform comparison?
I tried multiple things and options, but no luck.
My script so far:
# To get today's date
$Today=[datetime]::Today
# Output is 6. elokuuta 2015 0:00:00
$log_date = "Tue Aug 4 17:05:41 2015"
I read somewhere that by using new-object system.globalization.datetimeformatinfo
it can be achieved, but I don't know how to change the current date-time with this. https://technet.microsoft.com/en-us/library/ff730960.aspx
[DateTime] objects do not have a format. It just a number of ticks (0.0000001 second) passed since some point in time (01/01/0001 00:00:00.0000000). The format is only needed to save a [DateTime] object as a string or to display it to the user, since 635744160000000000 ticks is not really understandable to a user.
All you need is to parse the string to get a [DateTime] object:
$log_date = [datetime]::ParseExact('Tue Aug 4 17:05:41 2015','ddd MMM d HH:mm:ss yyyy',[cultureinfo]::InvariantCulture,'AllowInnerWhite')
Now as you have two [DateTime] objects you can compare them:
$Today -eq $log_date
$Today -lt $log_date
$Today -gt $log_date
Or find a difference between them:
$Today - $log_date
i create this script
$VarDay = (Get-Date).day
$VarMonth = (Get-Date).month
get-messagetrackinglog -Recipients:haavarot-from#my-domain.co.il -EventID "FAIL" -Start "09/20/14" -End "09/23/14" | export-csv c:\MailboxStatistics-$VarMonth-$VarDay.csv -encoding "utf8"
to create CSV file with the date name for FAIL mails from mail box
its work fine
but the only problem i cant found is to way to make it run daily wit no need to edit the DATES in the Ps code
-i want it to sat auto run at 22:00 every day and make the log for the some day only for 7 days
in the 8 day i want it to delete the old and create a new one
i need to save only the last 7 days
and idea?
-Start and -End accepts [System.DateTime] so you can just use Get-Date and play with the days using AddDays()
Straight from MSDN. You could do something like this
$endDate = Get-Date # This is today
$startDate = (Get-Date).AddDays(-7) # This is 7 days ago
If you would feel more comfortable with just the date and drop the time you can use the .ToString() method to format the time. Note that the datetime object would be lost as this returns a string.
$endDate = (Get-Date).ToString("MM/dd/yy")
$startDate = ((Get-Date).AddDays(-7)).ToString("MM/dd/yy")
More information on formatting dates can be found here