2012-09-19 47 views
2

我在編寫一個PowerShell腳本,它將生成一個包含兩列的信息表:名稱和日期(將從第三方應用程序中檢索 - 在本例中爲svn。可執行程序)。在PowerShell中解析日期時間

整體腳本運行良好,但我很努力地獲取服務器發送回DataTable的日期。這裏是我的腳本的簡化版本:

# Set up a DataTable and initialise columns 
$table = New-Object system.Data.DataTable 「Test Table」 
$col1 = New-Object system.Data.DataColumn Name,([string]) 
$col2 = New-Object system.Data.DataColumn DateFromServer,([DateTime]) 
$table.columns.add($col1) 
$table.columns.add($col2) 

# Create a new row and add the data 
$row = $table.NewRow() 
$row.Name = "Test" 
$lastCommit = GetDateFromExternalApp 
$lastCommit.GetType() # this returns DateTime as I would expect 
$row.DateFromServer = $lastCommit # this throws up an error 
$table.Rows.Add($row) 

# Output the table 
$table | Format-Table -AutoSize 

# This function simulates what the actual function does 
# (the real one goes to SVN and pulls down data, but it 
# ends up with the same resulting date) 
Function GetDateFromExternalApp 
{ 
    $externalAppDate = "2012-09-17T16:33:57.177516Z" 

    return [DateTime]($externalAppDate) 
} 

的問題(在上面的腳本註釋說明)是在功能似乎愉快地返回DateTime實例,當我嘗試添加到錶行的這DateFromServer列它扔了一個錯誤:

Exception setting "DateFromServer": "Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.IConvertible'.Couldn't store <18/09/2012 2:33:57 AM> in DateFromServer Column. Expected type is DateTime." At line:13 char:6 
+ $row. <<<< DateFromServer = $lastCommit 
    + CategoryInfo   : InvalidOperation: (:) [], RuntimeException 
    + FullyQualifiedErrorId : PropertyAssignmentException 

然而,調用$ lastCommit.GetType()表示,這確實是一個DateTime - 事實上,如果我在腳本的某處添加此行:

$lastCommit 

那麼我可以看到一個很好的格式化的日期時間,這表明它確實是分析它,並正確地將其轉換:

Date  : 18/09/2012 12:00:00 AM 
Day   : 18 
DayOfWeek : Tuesday 
DayOfYear : 262 
Hour  : 2 
Kind  : Local 
Millisecond : 177 
Minute  : 33 
Month  : 9 
Second  : 57 
Ticks  : 634835324371775160 
TimeOfDay : 02:33:57.1775160 
Year  : 2012 
DateTime : Tuesday, 18 September 2012 2:33:57 AM 

這樣我,爲什麼我得到上述異常挺納悶。我意識到PowerShell的功能與C#的返回值不同,但它在我看來就像函數返回正確的類型!

回答

3

我想知道這種行爲的原因。

無論如何,你可以通過將Date變量轉換爲DateTime或者明確聲明它爲一來解決這個問題。像這樣,

... 
$row.DateFromServer = [DateTime]$lastCommit # Doesn't throw exception 
... 

或者

... 
[DateTime]$lastCommit = GetDateFromExternalApp 
$row.DateFromServer = $lastCommit # Doesn't throw exception 
... 
+0

謝謝!這很好。是的,它對我來說似乎並不合邏輯,但是我又是新來的PowerShell,所以不確定標準等等。 – John

0

我懷疑的原因是錯誤消息指出:

「無法投類型的對象System.Management.Automation.PSObject「鍵入'System.IConvertible'...期望的類型是DateTime。「在行:13 char:6

這是說PowerShell試圖將$ lastCommit轉換爲日期和時間,但失敗。最好的辦法是,作爲vonPryz建議 - 將它轉換爲[日期時間]

爲了更清楚地看到問題,請嘗試在看兩個: $ lastcommit.gettype()和 $ row.DateFromServer.gettype()

我沒有GetDateFromExternalApp檢查

+0

該問題的示例代碼包含一個重現問題的僞GetDateFromExternalApp函數。 – vonPryz

+0

使用這個getdatefromexternalapp不會在這裏重現問題。運行此代碼給我這個: 名稱DateFromServer ---- -------------- 測試2012/9/17 5:33:57 PM –

+0

它也在我的系統上。你在哪個PSH版本上?該函數起作用,你是否也試過$ row.DateFromServer = $ lastCommit部分? – vonPryz

4

這裏的問題是由於PowerShell的類型適配系統(我會建議reporting this to Microsoft如果你還沒有這樣做)的一個錯誤。

當您在PowerShell中使用對象時,實際上您正在使用一個PSObject包裝器。大多數呼叫(如GetType)轉發到底層的對象,但你可以添加不與對象本身進行交互的其他成員:

PS> Get-Date | Add-Member NoteProperty Yowza 'for example' -PassThru | Format-List y* 
Yowza : for example 
Year : 2012 


通常這不是一個問題,因爲PowerShell有廣泛的類型強制能力。然而,在DataRow的情況下,似乎存在用於支持屬性訪問語法的DataRowAdapter類型的錯誤。如果直接使用the indexer,則該值將在發送到.NET類型之前正確解開,而不是$row.DateFromServer,該值爲$row['DateFromServer'] = $lastCommit。 ,或通過檢索BaseObject$lastCommit.PSObject.BaseObject):

您也可以自行展開的價值,無論是採用CAST([DateTime]$lastCommitvonPryz already showed)解決這個問題。

+0

謝謝!對於將獲取日期放入數據表中的問題,我一直耿耿於懷,而這也解決了它的問題。 – mbourgon