我创建了一些代码,以将双精度日期和时间值转换为另一个时区。当使用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;
}
}
}
您所谓的“双精度日期和时间值”也称为“ OLE自动化日期”或简称为“ OADate”。
OADates不传达任何时区信息。它们只是自1899年12月30日以来某个未知日历中的一点。此外,关于它们的编码方式还有一些奇怪的怪癖(请参阅这些MSDN文档中的说明),这使它们有些不受欢迎。如果可能的话,我会避免使用它们。
但是,您应始终将它们视为未指定。实际上,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
它时,将假定该值是根据源时区(在这种情况下为您的本地时区)而言的。虽然本地种类可以在这里工作,但这不是必需的。
至于为什么尝试本地类型时出错,我认为这是您遇到的错误:
“转换无法完成,因为所提供的日期时间不正确有那种属性集。例如,当Kind属性为DateTimeKind.Local,源时区必须是TimeZoneInfo.Local。 ”
正如错误所解释的DateTime
那样,TimeZoneInfo.ConvertTime
除非源时区特别来自,否则您不能将local传递给DateTimeKind.Local
。
源时区ID与本地时区ID匹配还不够,因为TimeZoneInfo.Local
特殊情况下需要考虑“自动调整夏令时”。有关详细信息,请参见这些MSDN文档。换一种说法:
TimeZoneInfo.Local != TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id)
最后,我认为您误会了DateTimeKind
。你说:
确定要正确转换时间,是否必须指定该值是本地时间并且属于某个时区?
“本地”中DateTimeKind.Local
和在TimeZoneInfo.Local
具体是指本地其中代码运行的计算机。这不是一个局部区域,它的局部区域。如果将DateTime
绑定到UTC或计算机自己的本地时区设置以外的其他时区,则DateTimeKind.Unspecified
使用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句