首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >替换TimeZone

替换TimeZone
EN

Stack Overflow用户
提问于 2018-05-10 16:30:47
回答 2查看 837关注 0票数 4

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

为了在. .ics/ical中填充开始/结束时间,DateTime被格式化为yyyyMMddTHHmmssZ。使用这种格式,2018年5月25日7:00 in (20180508T192840Z)总是看起来像服务器的山地标准时间(MST),而不是2018年5月25日7:00 in在选定的东部标准时间(EST)。

我如何用DateTimeDateTimeOffsetTimeZoneInfoNodaTime甚至string函数“替换”生成的不更改年份/月/日/小时/分钟的时区,以将其格式化为yyyyMMddTHHmmssZ

以下内容如下:

代码语言:javascript
复制
TimeZoneInfo destinationTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var converted = TimeZoneInfo.ConvertTime(dateTime1, destinationTimeZone);

或者:

代码语言:javascript
复制
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创建的DateTime.Now这样的方法来实现这一点?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-10 20:39:25

有几件事:

  • 您的格式说明符在末尾包含一个Z。not的字符串格式将其视为字符文字,因为它不是有效的日期时间格式说明符。注意,格式化标记区分大小写。作为文字,它只是被复制到输出--就像T一样。因此,您生成的这个字符串总是被解析它的任何东西解释为UTC,因为这就是Z在ISO8601标准中的意思。这是你所面临的问题的根本原因。 如果您想让它反映一个模糊的本地时间(因为时区可能在您的.ics中的其他地方?),那么完全忽略Z。但是,如果您打算包含时区偏移量,则可以使用K说明符来表示DateTime值,或者使用zzz说明符与DateTimeOffset值结合使用--这取决于您的特定需求。
  • 正如其他人所指出的,DateTime不知道时区,但也注意到DateTimeOffset也不知道,因为它只跟踪来自UTC的偏移量,而不是特定的时区。例如,它可以跟踪-07:00,但它不能告诉您它在山区时间。这就是野田时代( Noda )拥有ZonedDateTime类型的原因。.Net本身没有任何这样的内置类型。
  • 在您的代码中,并不是在调用TimeZoneInfo.ConvertTime时将考虑到dateTime1变量的.Kind。如果是DateTimeKind.Utc,那么结果将是确定性的。但是如果它是DateTimeKind.Unspecified,或者DateTimeKind.Local,那么它将被视为本地计算机的时区--在您的情况下,这个时区就是服务器时区。
  • 请注意,无论服务器的时区设置为什么,以同样的方式编写代码要好得多。这通常意味着避免DateTimeKind.Local,如DateTime.NowTimeZoneInfo.Local和其他。相反,使用DateTime.UtcNow获取当前的DateTime。或者,您可以使用DateTimeOffset.NowDateTimeOffset.UtcNow,或者在Noda的IClock实现上使用其中一个方法。

最后,尽管您的问题有几种可能的解决方案,但在特定时区中生成当前时间的最简单方法是:

代码语言:javascript
复制
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime utcNow = DateTime.UtcNow;
DateTime converted = TimeZoneInfo.ConvertTime(utcNow, destinationTimeZone);
string s = converted.ToString("yyyyMMddTHHmmss");

或者你可能想:

代码语言:javascript
复制
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTimeOffset utcNow = DateTimeOffset.UtcNow;
DateTimeOffset converted = TimeZoneInfo.ConvertTime(utcNow, destinationTimeZone);
string s = converted.ToString("yyyyMMddTHHmmsszzz").Replace(":","");

注意,最后通过:删除了Replace --这是因为在ISO8601的基本格式中,偏移应该类似于-0500而不是-05:00。不幸的是,没有格式说明符可以直接得到它。(只有ISO 8601扩展格式使用冒号)。

票数 3
EN

Stack Overflow用户

发布于 2018-05-10 18:04:00

DateTime类型不知道时区,它所知道的关于区域的一切都是DateTimeKind,它可以是LocalUtcUnspecified。字符串表示中包含的区域信息将基于Kind值和服务器时区。

您应该在您的场景中使用DateTimeOffset,它将日期、时间和时区信息存储在一个值中:

代码语言:javascript
复制
var dateTime = DateTime.Now; /*your date time here*/
var destinationTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var zonedDateTime = new DateTimeOffset(DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified), destinationTimeZone.BaseUtcOffset);
var dateTimeStr = zonedDateTime.ToString("o"/*your format goes here*/);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50277481

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档