当前位置: 首页 > 知识库问答 >
问题:

替换时区

魏元白
2023-03-14

我们正在尝试构建基本的事件日历功能,该功能允许用户创建事件并指定给定月、日、年、小时和分钟的开始时间以及时区(system.timezoneinfo.id)。CMS系统根据服务器的位置生成结果system.DateTime,比方说TimeZoneInfo.id山区标准时间。CMS没有在其日期选择器组件中提供指定时区的选项。但是,我们可以控制SQL datetime精度,默认设置为7

datetime被格式化为yyyymmddthhmmssz,以便在.ics/ical中填充开始/结束时间。使用这种格式,它会使2018年5月25日7:00PM(20180508T192840Z)始终看起来像服务器的山区标准时间(MST),而不是选择的东部标准时间(EST)中的2018年5月25日7:00PM。

如何将在不更改年/月/日/小时/分钟的情况下生成的datetimedatetimeoffsettimezoneinfonodatime或甚至string函数“替换”datetime的时区,以将其格式化为yyyymmddthhmmssz

以下内容:

TimeZoneInfo destinationTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var converted = TimeZoneInfo.ConvertTime(dateTime1, destinationTimeZone);

或:

LocalDateTime fromLocal = LocalDateTime.FromDateTime(dateTime1);
DateTimeZone fromZone = DateTimeZoneProviders.Tzdb["America/Denver"];
ZonedDateTime fromZoned = fromLocal.InZoneLeniently(fromZone);

DateTimeZone toZone = DateTimeZoneProviders.Tzdb["America/Chicago"];
ZonedDateTime toZoned = fromZoned.WithZone(toZone);
LocalDateTime toLocal = toZoned.LocalDateTime;
var result = toLocal.ToDateTimeUnspecified();

创建一个新的DateTime,将小时从CST调整为EST,这将不起作用,因为目标是使DateTime具有原始小时值,但具有TimeZoneInfo.id东部标准时间。

DateTime构造函数似乎没有指定TimeZoneInfo的构造函数,只有指定DateTimeKind的构造函数。

如何使用从datetime.now创建的datetime来完成这一任务?

共有1个答案

邹修真
2023-03-14

几件事:

>

  • 您的格式说明符在末尾包含z。这被.NET的字符串格式视为字符文本,因为它不是有效的日期时间格式说明符。请注意,格式标记区分大小写。作为文字,它只是复制到输出--就像t一样。因此,您生成的字符串总是会被解析它的任何东西解释为UTC,因为这是ISO8601标准中z的意思。这是你所面临问题的根本原因。

    如果您希望它反映一个不明确的本地时间(因为时区可能在.ics的其他地方?),那么就完全省略z。但是,如果您打算包含时区偏移量,则可以将k说明符用于datetime值,或者将zzz说明符与datetimeoffset值结合使用-这取决于您的具体需要。

    正如其他人指出的,datetime不知道时区,但也要注意,datetimeoffset也不知道,因为它只跟踪与UTC的偏移量,而不跟踪特定时区。例如,它可以跟踪-07:00,但它不能告诉你它处于山区时间。这就是Noda Time具有zoneddatetime类型的原因。.NET本身没有任何这样的内置类型。

    在您的代码中,并不是在对TimeZoneInfo.ConvertTime的调用中,将考虑DateTime1变量的.kind。如果是datetimekind.utc,那么结果将是确定性的。但如果它是DateTimeKind.unspecifiedDateTimeKind.local,则它将被视为本地计算机的时区-在您的情况下是服务器的时区。

    请注意,无论服务器的时区设置为什么,以行为相同的方式编写代码要好得多。这通常意味着避免DateTimeKind.Local,如DateTime.NowTimeZoneInfo.Local等。相反,使用datetime.utcNow获取当前的datetime。或者,您可以使用datetimeoffset.nowdatetimeoffset.utcnow,或者Noda Time的iclock实现中的方法之一。

    归根结底,尽管有几种可能的解决方案,但将当前时间生成为特定时区中的字符串的最简单的方案是:

    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    DateTime utcNow = DateTime.UtcNow;
    DateTime converted = TimeZoneInfo.ConvertTime(utcNow, destinationTimeZone);
    string s = converted.ToString("yyyyMMddTHHmmss");
    

    或者您可能需要:

    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    DateTimeOffset utcNow = DateTimeOffset.UtcNow;
    DateTimeOffset converted = TimeZoneInfo.ConvertTime(utcNow, destinationTimeZone);
    string s = converted.ToString("yyyyMMddTHHmmsszzz").Replace(":","");
    

    请注意,通过replace删除了结尾处的:-这是因为在ISO 8601基本格式中,偏移量应该类似于-0500而不是-05:00。不幸的是,没有格式说明符来直接获取它。(只有ISO 8601扩展格式使用冒号)。

  •  类似资料:
    • 这个问题在互联网上一次又一次地出现(即使是在SO上),但我还没有找到一个令人满意的解决方法: 如何在运行的web应用程序中更改/替换Javascript代码,而不重新加载页面? 很多人对此的回答是“你不能,因为这是不可能的”。IntelliJ IDEAs live edit插件的一些实验证明了这是可能的。但我不想为这个特性绑定到IDE。(加分:与浏览器无关) 下面是我尝试的: 将//#source

    • 我有以下代码: CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态){ 这就是我试图在xml文件中替换的内容: 这是怎么回事?无论如何要更新ID吗? 新堆栈跟踪:

    • 我正在尝试使用AST转换替换类的方法。 我首先检查该方法是否存在,然后将其删除(基于此)。 我看到集合上的大小发生了变化,但该方法仍然可以在类节点上访问。 删除该方法后,我想添加一个同名的新方法: 但是,这会导致以下错误: 正确的方法是什么? 更新:由于我打算做的就是替换该方法的现有功能,因此我创建了一个新的块语句,并使用 在现有方法上设置了它。

    • Git 对象是不可改变的,但它提供一种有趣的方式来用其他对象假装替换数据库中的 Git 对象。 replace 命令可以让你在 Git 中指定一个对象并可以声称“每次你遇到这个 Git 对象时,假装它是其他的东西”。 在你用一个不同的提交替换历史中的一个提交时,这会非常有用。 例如,你有一个大型的代码历史并想把自己的仓库分成一个短的历史和一个更大更长久的历史,短历史供新的开发者使用,后者给喜欢数据

    • 问题内容: 目的 我有一个简单的表,列出了名称(在局部视图中),并且在其上方有一个包含这些名称的下拉列表。目的是根据在下拉列表中选择的名称来过滤表。下拉列表中的选定值更改后,应立即进行过滤,并且应仅再次呈现部分视图。 问题 当我在下拉列表中选择一个值时,部分视图不会在其他视图中呈现,而是显示为整个页面。但是,当我在Ajax.BeginForm块中包含一个提交按钮并触发对提交按钮的操作时,它确实可以

    • 我正在使用一些非常古老的。 我试图通过删除非字母字符(标点符号和数字等)来净化一些输入 通常我会做这样的事情: 然而,是在中引入的!所以它不会编译!http://docs.oracle.com/javase/7/docs/api/java/lang/string.html#ReplaceAll(java.lang.string,java.lang.string) 在之前,我们是如何做到这一点的?