在 Powershell 中使用不寻常的日期格式?

Working with unusual date formats in Powershell?

我正在开发一个基于 GUI 的 Powershell 工具,以帮助用户轻松发现他们的 AD 密码何时到期。由于 Covid 限制,大多数用户不在现场,而是依靠 VPN 连接到 AD。这样做的一个副产品是,许多人没有看到 Windows 中的自动弹出窗口提醒他们尽快设置新密码。那些在现场的人会看到通知 OK。这不是一个组策略问题。该工具将以两种不同的语言推出 - 一种代表 'mothership'(通常不说英语的地方),另一种代表所有其他国家/地区的英语。

一些(大部分)东欧国家/地区使用短日期格式,读起来像 'd.M.yyyy.' - 根据设置菜单更改 Windows 中的 'Region' 设置。

该工具计算今天和到期数据之间的差异,并将天数输出到文本字段。实际到期时间正确显示在其自己的文本字段中。

它背后的一些源代码...

$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. 

执行脚本时会抛出几个错误。

第一个是...

Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid  DateTime."

其他人会跟进,例如

You cannot call a method on a null-valued expression.

因为无法计算今天和到期日之间的差异

有什么简单的解决方法吗?我宁愿避免为每个 country/culture 编写一长串 'if' 语句。谢谢!

我相信代码可以更优雅一些,这将在以后的版本中解决。现在,让它处理一些更晦涩的日期格式是我的首要任务。

还有一点我要强调的是,此工具以 'read only' 的能力运行。未使用 'Set-Item' 命令。

此致,

WL

您有 2 个问题:

  • 可互换使用的多种日期格式
  • 一些 字符串上的尾随点

第一个问题可以通过将多个格式字符串传递给 ParseExact() 来解决 - 它会按顺序尝试每个字符串,直到成功解析输入字符串(或到达列表末尾):

[datetime]::ParseExact($password_expiry_as_string, [string[]]@('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)

第二个问题可以通过修剪尾随点来解决:

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