2016-11-15 84 views
0

我正在嘗試製作一個小幫手應用程序來協助閱讀SCCM日誌。解析日期一直非常簡單直到我到達時區偏移量。它通常以「+ ???」的形式出現。字面示例:「11-01-2016 11:44:25.630 + 480」奇怪的日期分析結果

DateTime.parse()可以在大多數情況下處理此問題。但偶爾我遇到了引發異常的時間戳。我無法弄清楚爲什麼。這是我需要幫助的地方。請參閱下面的示例代碼:

Dim dateA As DateTime = Nothing 
Dim dateB As DateTime = Nothing 
Dim dateStr_A As String = "11-07-2016 16:43:51.541+600" 
Dim dateStr_B As String = "11-01-2016 11:44:25.630+480" 

dateA = DateTime.Parse(dateStr_A) 
dateB = DateTime.Parse(dateStr_B) 

MsgBox(dateA.ToString & vbCrLf & dateB.ToString) 

如果運行它似乎dateStr_B是一個無效的時間戳?爲什麼是這樣?我試圖弄清楚如何使用.zip使用.ParseExact()格式來處理+480如下所示Date Formatting MSDN

我是否缺少與時區偏移量有關的東西?我搜索了高和低,但這些SCCM日誌似乎使用非標準的方式來表示偏移量。任何洞察力將不勝感激

回答

0

問題是,+480確實是一個無效的偏移量。 UTC的偏移量格式(使用"zzz" Custom Format Specifier時產生)爲小時和分鐘。 +600比UTC早6小時0分,這是有效的。 +480將比UTC UTC時間提前4小時80分鐘,由於分鐘數不能超過59,因此無效。

如果您有一些使用偏移量的日期和時間字符串的外部源只需幾分鐘(即+600表示10小時,+480表示8小時),則需要在使用DateTime.ParseDateTime.ParseExact之前調整偏移量。

[編輯] 以下函數以分鐘爲單位獲取正數或負數偏移量(任意數量的數字)的時間戳,並返回DateTime。如果時間戳不是有效的格式,它會引發一個ArgumentException。

Public Function DateTimeFromSCCM(ByVal ts As String) As DateTime 
    Dim pos As Integer = ts.LastIndexOfAny({"+"c, "-"c}) 
    If pos < 0 Then Throw New ArgumentException("Timestamp must contain a timezone offset", "ts") 

    Dim offset As Integer 
    If Not Integer.TryParse(ts.Substring(pos + 1), offset) Then 
     Throw New ArgumentException("Timezone offset is not numeric", "ts") 
    End If 

    Dim hours As Integer = offset \ 60 
    Dim minutes As Integer = offset Mod 60 

    Dim timestamp As String = ts.Substring(0, pos + 1) & hours.ToString & minutes.ToString("00") 
    Dim result As DateTime 
    If Not DateTime.TryParse(timestamp, result) Then 
     Throw New ArgumentException("Invalid timestamp", "ts") 
    End If 
    Return result 
End Function 
+0

謝謝你的洞察力。我已經根據您的建議添加了我的試驗性解決方案。 – Wariv

+0

文章編輯:非常酷。我絕對在這裏學習很多。我很感激你花時間來處理這個問題。 – Wariv

0

謝謝你的洞察力。我有一種感覺,我需要手動處理。我只是想確保在這個過程中我沒有錯過簡單的事情。我對日期和時間格式的知識有點欠缺。

因此,我改變了我的代碼,以便它處理偏移量。當然,我將不得不在最終產品中添加更多的輸入驗證。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     Dim dateA As DateTime = Nothing 
     Dim dateB As DateTime = Nothing 
     Dim dateStr_A As String = correctOffset("11-07-2016 16:43:51.541+600") 
     Dim dateStr_B As String = correctOffset("11-07-2016 16:43:51.541+480") 

     dateA = DateTime.Parse(dateStr_A) 
     dateB = DateTime.Parse(dateStr_B) 

     MsgBox(dateA.ToString & vbCrLf & dateB.ToString) 
    End Sub 

    Public Function correctOffset(ByVal ts As String) 
     Dim offset As Integer = CInt(ts.Substring(ts.Length - 3)) 
     Dim offHour As Integer = offset/60 
     Dim offMin As Integer = offset - (offHour * 60) 

     Dim strhour As String = Nothing 
     Dim strmin As String = Nothing 

     If offHour <= 9 Then 
      strhour = "0" & CStr(offHour) 
     Else 
      strhour = CStr(offHour) 
     End If 

     If offMin <= 9 Then 
      strmin = "0" & CStr(offMin) 
     Else 
      strmin = CStr(offMin) 
     End If 

     Return ts.Substring(0, ts.Length - 3) & strhour & ":" & strmin 
    End Function 
+0

我不熟悉SCCM時間戳的格式(這就是爲什麼我沒有嘗試在我的答案中編寫偏移校正的原因)。您發佈的代碼似乎與您的問題中的兩個示例一起工作,但您是否需要處理其他情況?偏移量可以是負值而不是正值?偏移總是三個字符還是兩個或四個字符? – Blackwood

+0

我建議進行一些更改以確保代碼將使用「Option Strict On」進行編譯。 (1)在correctOffset函數中包含'As'子句:'Public Function correctOffset(ByVal ts As String)As String'。 (2)除以60表示結果是一個整數:'Dim offHour As Integer = offset \ 60',使用整除運算符('\')。 – Blackwood

+0

我將不得不檢查一些我的服務器日誌,看看如何處理少於或超過3位數的情況。我個人還沒有看到,但那可能是因爲我當時沒有在尋找那些案件。如果確實使用負偏移量,我高度懷疑我會看到超過4位數,因爲12小時是720分鐘,如果您可以在24小時內前後移動,超過12小時偏移量將會很奇怪。 感謝您使用(')的提示。我不知道那是一件事。 我一定會爲生產版本創建一個嚴格的輸入驗證檢查。 – Wariv