2014-03-28 88 views
1

我已經創建了一些代碼來將雙精度日期時間值&轉換爲另一個時區。它給出的行爲我只是不明白什麼時候使用DateTimeKind.Local來代替DateTimeKind.Unspecified。將雙精度日期和時間值轉換爲另一個時區?

我的想法是,傳入方法ConvertTime的雙精度值完全與其地理上下文無關。當然,爲了正確地轉換時間,有必要指定該值是當地時間並屬於某個時區?

我試圖確定本地源時間已正確轉換爲本地目標時間,並觀察夏令時,而不考慮主機的時區設置。

從這個概念我嘗試以指定

DateTime sourceDT = DateTime.SpecifyKind(inDT, DateTimeKind.Local); 

但這會導致不被轉換的時間工作。如果我指定

DateTime sourceDT = DateTime.SpecifyKind(inDT, DateTimeKind.Unspecified); 

然後發生轉換。

有人可以請解釋爲什麼DateTimeKind.Local不被接受爲時間轉換中的有效規範以及如何實現我正在嘗試的內容。

namespace ConvertTime 
{ 
public interface ConvertTimeClass 
{ 
    double ConvertTime(double inTime, [MarshalAs(UnmanagedType.LPStr)] string sourceTZ,  [MarshalAs(UnmanagedType.LPStr)] string destTZ); 
} 

public class ManagedClass : ConvertTimeClass 
{ 
    public double ConvertTime(double inTime, [MarshalAs(UnmanagedType.LPStr)] string sourceTZ, [MarshalAs(UnmanagedType.LPStr)] string destTZ) 
    { 
     DateTime inDT = DateTime.FromOADate(inTime);//convert decimal date and time value to a DateTime object. 
     DateTime sourceDT = DateTime.SpecifyKind(inDT, DateTimeKind.Unspecified);//specify that the time represents a local time and save into a new object. 
     TimeZoneInfo sourceTZI = TimeZoneInfo.FindSystemTimeZoneById(sourceTZ); 
     TimeZoneInfo destTZI = TimeZoneInfo.FindSystemTimeZoneById(destTZ); 
     DateTime destDT = TimeZoneInfo.ConvertTime(sourceDT, sourceTZI, destTZI);//convert time. FAILS WHEN DateTimeKind.Local is specified 

     double outTime = destDT.ToOADate();//extract the decimal date & time value 
     return outTime; 
    } 
} 

}

回答

4

你提到的「雙精度日期和時間值」什麼是也被稱爲「OLE自動化日期」或「OADate」的簡稱。

OADates不傳達任何時區信息。它們只是自1899年12月30日以來的一個未知日曆中的一個點。另外,關於它們如何被編碼有一些奇怪的怪癖(參見these MSDN docs中的評論),這使得它們稍微不合需要。如果可能的話,我會盡量避免。

儘管如此,你應該始終把它們視爲未指定。實際上,您撥打的FromOADate方法已將其返回爲Unspecified種類,因此完全沒有理由致電DateTime.SpecifyKind。總之,你的函數應該簡單地:

public double ConvertTime(double inTime, string sourceTZ, string destTZ) 
{ 
    DateTime sourceDT = DateTime.FromOADate(inTime); 
    TimeZoneInfo sourceTZI = TimeZoneInfo.FindSystemTimeZoneById(sourceTZ); 
    TimeZoneInfo destTZI = TimeZoneInfo.FindSystemTimeZoneById(destTZ); 
    DateTime destDT = TimeZoneInfo.ConvertTime(sourceDT, sourceTZI, destTZI); 
    return destDT.ToOADate(); 
} 

但是,如果你的使用情況要求假定輸入時間是計算機的本地時區,那麼您將創建一個不同方法代替:

public double ConvertFromLocalTime(double inTime, string destTZ) 
{ 
    DateTime sourceDT = DateTime.FromOADate(inTime); 
    TimeZoneInfo sourceTZI = TimeZoneInfo.Local; 
    TimeZoneInfo destTZI = TimeZoneInfo.FindSystemTimeZoneById(destTZ); 
    DateTime destDT = TimeZoneInfo.ConvertTime(sourceDT, sourceTZI, destTZI); 
    return destDT.ToOADate(); 
} 

您仍然不需要指定本地類型,因爲當未指定的DateTime傳遞給TimeZoneInfo.ConvertTime時,它假定該值是以源時區的形式表示的 - 這是您在本例中的本地時區。雖然本地種工作在這裏,它不是必需的。

至於爲什麼你想本地樣時得到的錯誤,我想這是你有錯誤:

「轉換無法完成,因爲所提供的DateTime沒有Kind屬性集正確。例如,當Kind屬性爲DateTimeKind.Local時,源時區必須爲TimeZoneInfo.Local。

由於錯誤解釋,你可以在一個DateTime與本地種不傳遞給TimeZoneInfo.ConvertTime除非源時區是專門從DateTimeKind.Local拍攝。

這是不夠的來源時區ID匹配。本地時區ID,因爲TimeZoneInfo.Local有考慮到特殊情況下,「自動調整爲夏令時時鐘」選項見these MSDN docs for details換句話說:

TimeZoneInfo.Local != TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id) 

最後,我想你誤解了DateTimeKind。你說:

肯定的時間來正確轉換,必須指定該值是本地時間,屬於一定的時區?

DateTimeKind.LocalTimeZoneInfo.Local的「本地」具體地是指本地到運行代碼計算機。它不是a本地區域,它是本地區域。如果DateTime與UTC或計算機本地時區設置等其他時區相關,則使用DateTimeKind.Unspecified

相關問題