如何更改.NET中的默认时区?

news/2024/10/3 17:10:52

除了"在操作系统中修改时区信息,然后重启.NET应用程序,使其生效"之外。如何在不修改操作系统时区的前提下,修改.NET中的默认时区呢?

这是一位 同学兼同事 于5月21日在技术群里问的问题,我当时简单地研究了一下,就写出来了。

现在写文章分享给大家,虽然我觉得这种需求非常小众,几乎不会有人用到。

正文

正常手段下,.NET是不允许开发者修改默认时区的,它没有公开这样的API。

在 .NET 中,管理时区的类型叫 TimeZoneInfo,它位于 System 命名空间下,由 System.Private.CoreLib.dll 提供。

使用 ILSpy 反编译 System.Private.CoreLib.dll,找到 TimeZoneInfo 类型,我们可以看到 TimeZoneInfo.Local 指向一个私有字段 s_cachedData 的成员属性 Local,该字段类型是一个属于 TimeZoneInfo 的私有嵌套类型 CachedData

当首次访问 CachedData.Local 时,它会先检查 _localTimeZone 私有字段是否有值。如果没有值,则调用 CreateLocal 方法从操作系统获取时区信息并且赋值。

看到了这里,我脑海里就浮现了两种方案:

  1. 使用 hook 技术挟持并修改 win32 api 返回的时区信息。
  2. 使用 reflection 技术反射并且修改时区信息。

方案1的优点是稳定,但可能会被杀毒软件报毒。

方案2的优点是不会报毒,但可能不稳定。

为什么说方案2不稳定呢?因为 s_cachedData 私有字段值有可能在某个时候被重置。

现在我们来看看方案2的实现:

public static bool TrySetLocalTimeZoneInfo(TimeZoneInfo timeZoneInfo)
{Type timeZoneInfoType = typeof(TimeZoneInfo);// 获取TimeZoneInfo类型的私有静态字段成员信息s_cachedDataFieldInfo cachedDataFieldInfo = timeZoneInfoType.GetField("s_cachedData", BindingFlags.NonPublic | BindingFlags.Static);if (cachedDataFieldInfo == null){return false;}// 获取TimeZoneInfo类型的私有嵌套类型CachedDataType cachedDataType = timeZoneInfoType.GetNestedType("CachedData", BindingFlags.NonPublic);if (cachedDataType == null){return false;}// 获取CachedData类型的私有字段成员信息_localTimeZoneFieldInfo localTimeZoneFieldInfo = cachedDataType.GetField("_localTimeZone", BindingFlags.NonPublic | BindingFlags.Instance);if (localTimeZoneFieldInfo == null){return false;}// 获取TimeZoneInfo类型的私有静态字段s_cachedData值object cachedData = cachedDataFieldInfo.GetValue(null);if (cachedData == null){return false;}// 设置私有字段的值localTimeZoneFieldInfo.SetValue(cachedData, timeZoneInfo);return true;
}

PS: 该方法代码实际测试在 .NET Core 3.1, .NET 5.0, .NET 6.0, .NET 7.0, .NET 8.0 都可以正常工作。

用法:

void Main()
{// 设置前Console.WriteLine(TimeZoneInfo.Local);// 修改为 GMT 时区TimeZoneInfo hkTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");bool setResult = TrySetLocalTimeZoneInfo(hkTimeZoneInfo);// 设置后Console.WriteLine(TimeZoneInfo.Local);
}

注意:这种方案需要严谨测试,反复验证。

因为是篡改.NET内部私有变量,不知道是否会引起其它后果。

比如.NET内部其它API没有使用 TimeZoneInfo.Local,而是自己在其它地方又缓存了一套 TimeZoneInfo,那就GG了。

又比如,需要检查整个 .NET Runtime 和其它第三方组件,是否有调用 TimeZoneInfo.ClearCachedData 静态方法 或者 调用 CultureInfo.ClearCachedData 对象方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/44561.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

vulnhub - Geisha

目录扫描时要注意端口vulnhub - Geisha 描述 Machine Name: Geisha Author : SunCSR Goal: Get the root flag of the target. Difficulty: Medium/Intermediate Level DHCP Enabled Tested: VMware Workstation 15.x Pro & VirtualBox 6.x (This works better with VMware…

centos7的虚拟机只显示本地回环

问题:安装好的centos7的虚拟机只显示本地回环,没有其它网卡信息虚拟机 : centps7.9centos安装好后,登录成功后,输入ip a只显示本地127.0.0.1,而不显示ens33的网卡和ip信息,具体详情如下图所示:输入命令systemctl status network.service 不管得到的结果是下面的任意一个或…

纯碱

之前走出了5波驱动 阶段性反弹后 中期要跌的

【知识点】图与图论入门

两三个星期没有发布新文章了,今天再来讲一个新的数据结构:图。何为图论 见名知意,图论 (Graph Theory) 就是研究 图 (Graph) 的数学理论和方法。图是一种抽象的数据结构,由 节点 (Node) 和 连接这些节点的 边 (Edge) 组成。图论在计算机科学、网络分析、物流、社会网络分析…

ASP.NET Core之Serilog、SEQ、ILogger构建可视化日志

一、前言在上一章节中使用NLog+SEQ+ILogger构建可视化日志,本章基于Serilog来构建可视化日志。Serilog是.NET中一款非常出色的结构化日志的日志库,其与NLog对比在前一章节进行了说明。Serilog项目不仅仅包含核心项目Seirlog,而且还提供了很多接收器Sinks(超过100个),这些接…

【知识点】深度优先搜索 Depth First Search

深度优先搜索 Depth First Search去年发布的笔记,今年加以改编。 世界上只有两种人,一种是讨厌递归的人,另一种是讨厌递归后又重新爱上递归的人...搜索算法被广泛的应用在计算机领域中。搜索算法的本质就是通过暴力枚举以及模拟的方式来求得最终的答案。但普通的暴力枚举局限…

linux Typora修改Windows文件产生乱码(未解决)

问题如同所示,出现了乱码,而且不同于普通的乱码,英文字符之类的也没有保留下来(说明不是编码格式问题),反而出现了红圈中的那些本不存在的字符(搜了一下似乎和Oracle有关)。 未解决 我猜测是linux和windows的文件系统不同导致修改文件使得文件损坏。 只能说多做备份,幸…

LVGL库的bar控件

进度条(lv_bar) 概述 1.进度条对象(组件)有一个背景和一个指示器. 指示器的宽度根据进度条的当前值2.自动设置. 3.如果设置进度条的宽度小于其高度,就可以创建出垂直摆放的进度条 4.不仅可以设置结束,还可以设置进度条的起始值,从而改变指标的起始位置样式和零件 LV_PART_MAI…