GoF*_*ter 1 c# double time timezone datetime
我创建了一些代码来将双精度日期和时间值转换为另一个时区.当使用DateTimeKind.Local代替DateTimeKind.Unspecified时,它给出了我不理解的行为.
我的想法是传递给ConvertTime方法的双精度值完全脱离了它的地理上下文.当然,要正确转换的时间,有必要指定该值是本地时间并属于某个时区吗?
我正在尝试确保将本地源时间正确转换为本地目标时间并观察夏令时,而不考虑主机的时区设置.
从这个概念开始,我试着指出
DateTime sourceDT = DateTime.SpecifyKind(inDT, DateTimeKind.Local);
Run Code Online (Sandbox Code Playgroud)
但这会导致时间不被转换.如果我指定
DateTime sourceDT = DateTime.SpecifyKind(inDT, DateTimeKind.Unspecified);
Run Code Online (Sandbox Code Playgroud)
然后转换发生.
有人可以解释为什么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;
}
}
Run Code Online (Sandbox Code Playgroud)
}
您所谓的"双精度日期和时间值"也称为"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();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您的用例要求假设输入时间是计算机的本地时区,那么您将创建一个不同的方法:
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();
}
Run Code Online (Sandbox Code Playgroud)
您仍然不需要指定本地类型,因为当未指定DateTime传递给TimeZoneInfo.ConvertTime它时,假定该值是根据源时区 - 在这种情况下是您的本地时区.虽然本地人可以在这里工作,但这不是必需的.
至于为什么你在尝试本地类时遇到错误,我认为这是你的错误:
"转换无法完成,因为提供的DateTime没有正确设置Kind属性.例如,当Kind属性为DateTimeKind.Local时,源时区必须为TimeZoneInfo.Local. "
正如错误所解释的DateTime那样,TimeZoneInfo.ConvertTime除非专门从中获取源时区,否则无法传入本地类型DateTimeKind.Local.
源时区ID与本地时区ID匹配是不够的,因为TimeZoneInfo.Local有一个特殊情况考虑"自动调整夏令时的时钟"选项.有关详细信息,请参阅这些MSDN文档.换一种说法:
TimeZoneInfo.Local != TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id)
Run Code Online (Sandbox Code Playgroud)
最后,我想你误解了DateTimeKind.你说:
当然,要正确转换的时间,有必要指定该值是本地时间并属于某个时区吗?
"本地"in DateTimeKind.Local和in TimeZoneInfo.Local具体表示运行代码的计算机本地.这不是一个局部区域,它的局部区域.如果DateTime它与UTC或计算机自己的本地时区设置之间的某个其他时区绑定,则DateTimeKind.Unspecified使用.
| 归档时间: |
|
| 查看次数: |
865 次 |
| 最近记录: |