2014-03-28 40 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

相关问题