Silverlight时区转换

6

我正在尝试将一个WPF应用程序迁移到SilverLight 4。

在WPF应用程序中,使用TimeZoneInfo.FindSystemTimeZoneById()和TimeZoneInfo.ConvertTimeFromUtc()将特定时区的DateTime转换为另一个特定时区的DateTime。

但是在SilverLight 4中找不到这两个函数。SilverLight似乎仅支持Utc和本地时间之间的时区转换。

是否有办法在SilverLight中将DateTime从任何时区转换为任何其他时区?

3个回答

2

很遗憾,目前没有标准的功能来实现这一点。

让我们通过反射来检查TimeZoneInfo.FindSystemTimeZoneById()方法是如何工作的。它只需要从s_systemTimeZones字段中取一个值:

private static Dictionary<string, TimeZoneInfo> s_systemTimeZones
{
    get
    {
        if (s_hiddenSystemTimeZones == null)
        {
            s_hiddenSystemTimeZones = new Dictionary<string, TimeZoneInfo>();
        }
        return s_hiddenSystemTimeZones;
    }
    set
    {
        s_hiddenSystemTimeZones = value;
    }
}

这个字段存储了所有可用的TimeZoneInfo。当您调用FindSystemTimeZoneById(id)时,它只是从预先填充的字典中选择一些值。我不知道这个字典何时初始化以及用于初始化的哪些值。但是来自此线程的人说TimeZoneInfo使用来自注册表的值:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zones。
最明显的方法是创建自己的Dictionary字典并填充它的值。类似这样:
Dictionary<string, TimeZoneInfo> dictionary = new Dictionary<string, TimeZoneInfo>();
TimeZoneInfo info = new TimeZoneInfo("ID", new TimeSpan(0, 1, 0, 0), "SomeCultureName", "Some Standard Time", "Some Daylight Time", null, true);
dictionary.Add("Some time", info);

但是还有一个问题:TimeZoneInfo构造函数是私有的。因此,如果您想使用FindSystemTimeZoneById()和ConvertTimeFromUtc()功能,则必须从头开始实现它。创建一个表示时区的类,创建并填充该类的字典与时区信息等等...


这不是很好的消息,我知道。但我希望对您有用 :)


1
有点晚了,但我之前做过这个并在MS社区网站上发布供人们使用,因为经常被问到。我没有做时区ID的查找,但我在我的SL应用程序中使用了FromSerializedString()方法。我的Web服务将ToSerializedString()数据作为字符串属性传递,而在SL中,我只需根据需要使用此对象。我对TimeZoneInfo对象进行了反射。

https://github.com/TWhidden/DevStuff/blob/master/StackOverflow/TimeZoneInfo.cs

不确定这是否对您有帮助(或任何未来阅读此帖子的人)。

这很有趣,解决了我的问题。我正在使用它来处理V3 Silverlight,所以它应该适用于4/5,但也可能已经被微软改进了。

更新于2017-04-12:链接到GitHub,在PCL lib中使用此功能。应该适用于SL,但我们像微软多年前一样放弃了它。


更新为使用 Github 链接。 - TravisWhidden

0

如果有人遇到这个问题,这是我找到的解决方法...

Microsoft参考源代码中的TimeZoneInfo(在完整的.NET 4 CLR中)包括一个TryGetTimeZoneByRegistryKey()方法,该方法从注册表键HKLM\Software\Microsoft\Windows NT\CurrentVersion\Time Zones获取时区。

我猜如果您正在编写受信任的Silverlight应用程序,您可以使用P/Invoke来进行注册表查找。

对于我们的应用程序,我们不想显示要求完全信任权限的对话框。我进行了更多搜索,并发现Stephane Delcroix的开源实现 - 我不确定是否有比该链接更官方的来源。它与Unix时区数据库格式(zoneinfo)一起工作,您可以从IANA 下载

时区数据库非常庞大,如果您将其包含在Silverlight应用程序中,它会使应用程序变得臃肿。但我们只需要支持几个时区。我从数据库中取了一个子集,并将其打包到我们的Silverlight应用程序中作为资源;然后我修改了Stephane的代码,使其从资源流中读取而不是从文件系统中读取。由于没有/etc/localtime,我不得不删除所有本地时间功能。但我们只需要命名的时区以及在这些时区和UTC之间进行转换的能力。这种方法似乎可以正常工作。


嗯,实际上我没有使用IANA下载 - 我只是从我们网络中最近的Linux机器的 /etc/zoneinfo 目录中复制了内容。原来IANA文件是文本格式的,你需要通过一个时区编译器(“zic”)运行它们。 "zic"源代码也在同一页上;但如果你有一个Linux机器可以获取二进制文件,那么使用二进制文件会更容易些。 - Richard Beier
这里有一个GitHub版本链接(https://github.com/mono/mono/tree/master/mcs/class/System.Core/System)。 - Richard Beier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接