我正在使用 powershell 脚本来协助数据库更新/解析等。因为我们的数据库服务器不允许我们在同一脚本中进行查询和更新,所以我需要实际查询数据,使用 powershell 在我的计算机上解析它,然后根据解析的查询构建一个新的更新语句。为了帮助解决这个问题,我需要在 powershell 和 SQL 之间正确转换数据类型。我编写了以下函数来协助解决此问题,但它没有正确解析时间戳,并且传递给它的任何时间戳都会导致函数返回“字符串”并将 $setDate 变量保留为 $null
$myDate = '5/10/2023'
function getDataType {
param($inputData)
#check if input data is null
if (!$inputData) {
return 'null'
}
#check if variable can be cast as a timestamp
try {
#build an array of possible timestamp formats
$dateFormats = @('M/d/yyyy','M/dd/yyyy','MM/d/yyyy','MM/dd/yyyy','MM-dd-yyyy HH:mm:ss','MM-dd-yyyy HH:mm','yyyy-MM-dd HH.mm.ss')
foreach ($format in $dateFormats) {
if ([DateTime]::TryParseExact($inputData, $format, $null)) {
$global:setDate = [datetime]::ParseExact($inputData, $format, $null).ToString('yyyy-MM-dd HH:mm:ss')
return 'timestamp'
break
}
}
}
catch {
write-verbose 'not a timestamp'
}
#check if data is a number
try {
if ([int]$inputData) {
return 'number'
}
}
catch {
write-verbose 'not a number'
}
#assumes input is a string if it is not null, not a date, and not a number
return 'string'
}
getDataType($myDate) #should return 'timestamp' but returns 'string'
write-host "the date is $setDate" #should return "the date is 2023-05-10 00:00:00" but returns nothing
[DateTime]::TryParseExact
调用的参数并引发错误,您只是没有看到它,因为 Write-Verbose
没有 -Verbose
参数来生成详细输出,一个最小的例子:
try {
[DateTime]::TryParseExact('5/10/2023', 'M/dd/yyyy', $null)
}
catch {
Write-Verbose 'not a timestamp' -Verbose
}
# Outputs: VERBOSE: not a timestamp
正确的方法调用是将缺少的参数添加到此重载中:
[DateTime]::TryParseExact(
'5/10/2023', # string s
'M/dd/yyyy', # string? format
[cultureinfo]::InvariantCulture, # IFormatProvider? provider
[System.Globalization.DateTimeStyles]::None, # DateTimeStyles style
[ref] [datetime] 0) # out DateTime result
您似乎还想重复调用此函数,您应该注意重复的函数调用是昂贵的,因为我建议您将函数更改为静态方法,这样就不会受到影响这。这是您想要完成的工作版本:
class MyType {
static [string[]] $Formats = @(
'M/d/yyyy'
'M/dd/yyyy'
'MM/d/yyyy'
'MM/dd/yyyy'
'MM-dd-yyyy HH:mm:ss'
'MM-dd-yyyy HH:mm'
'yyyy-MM-dd HH.mm.ss'
)
static [string] GetDataType([object] $inputData, [ref] $out) {
if([string]::IsNullOrWhiteSpace($inputData)) {
return 'null or empty string'
}
if([int]::TryParse($inputData, [ref] $null)) {
return 'its an integer'
}
# no need for a loop here, `TryParseExact` has an `string?[]? formats` overload for this ;)
$isDate = [datetime]::TryParseExact(
$inputData,
[MyType]::Formats,
[cultureinfo]::InvariantCulture,
[System.Globalization.DateTimeStyles]::None, # You should define this one
$out)
if($isDate) {
return 'its a datetime'
}
return 'undetermined string'
}
}
$myDate = '5/10/2023'
$myOutVar = [datetime]::new(0)
$result = [MyType]::GetDataType($myDate, [ref] $myOutVar)
if($result -eq 'its a datetime') {
return $myOutVar
}
$result
如果您不需要指定自定义日期时间格式,则像 Get-Date cmdlet 这样的东西应该捕获有效的日期和时间戳。如果您想考虑使用 Get-Date 时会失败的句点格式,请使用像这样的替换...
# Below example captured all dates in desired string format
$SetDates = @(
'5/9/2023',
'5/10/2023',
'05/9/2023',
'05/10/2023',
'05-10-2023 12:05:02',
'05-10-2023 12:05',
'2023-05-10 12.05.02'
) | ForEach-Object {
Get-Date -Date $($_ -replace '\.',':') -Format 'yyyy-MM-dd HH:mm:ss'
}
$设置日期
2023-05-09 00:00:00
2023-05-10 00:00:00
2023-05-09 00:00:00
2023-05-10 00:00:00
2023-05-10 12:05:02
2023-05-10 12:05:00
2023-05-10 12:05:02