如何在不转换时间的情况下更改ZonedDateTime的Timzone

时间:2019-06-18 20:56:29

标签: c# .net datetime datetimeoffset nodatime

我有一个ZonedDateTime,它是使用DateTimeOffset和时区ID(字符串)创建的,还有一个DateTimeZone

我遇到的特殊情况是,我需要更改ZonedDateTime的Zone而不实际转换时间(即我有18:00 UTC-4:00,我想将其更改为18:00 UTC-8 相应地转换18:00)

我发现的唯一相关功能是.WithZone(DateTimeZone),但这似乎可以根据提供的区域转换我的时间

如何在不转换时间的情况下更改ZonedDateTime的“时区”?

编辑我发现了一个似乎可行的解决方案:

private DateTimeOffset myFunction(DateTimeOffset dateTimeOffset, string timeZoneId) {
    // get the DateTimeZone (i.e. Etc/GMT)
    DateTimeZone timezone = DateTimeZoneProviders.Tzdb[timeZoneId];

    // create a new DTO with the previous date/time values, but with the DateTimeZone Offset
    var newDTO = new DateTimeOffset(dateTimeOffset.DateTime, timezone.GetUtcOffset(SystemClock.Instance.GetCurrentInstant()).ToTimeSpan());

    // create a ZonedDateTime based on the new DTO
    var nodaDTO = ZonedDateTime.FromDateTimeOffset(newDTO);

    // the correct datetime in the correct zone
    var finalProduct = nodaDTO.WithZone(timezone);

    return finalProduct.ToDateTimeOffset();
}

2 个答案:

答案 0 :(得分:5)

如评论中所示,通常,这样做的愿望表明上游出现了一些问题-如果可以在此处修复,则应该这样做。

如果最终遇到DateTimeOffset的情况,其中局部绝对正确,但偏移量不正确,并且您确实无法更早地修复数据,那么您需要找到在当地时间更正UTC偏移量。重要的是要注意,本地时间可能是模棱两可的(如果发生在“后退”过渡期间)或被跳过(如果发生在“后退”过渡期间),那么您应该弄清楚该情况下的处理方法。

您可以使用DateTimeZone.MapLocal

private DateTimeOffset myFunction(DateTimeOffset dateTimeOffset, string timeZoneId)
{
    var unspecifiedDateTime = DateTime.SpecifyKind(dateTimeOffset.DateTime, DateTimeKind.Unspecified);
    var zone = DateTimeZoneProviders.Tzdb[timeZoneId];
    var local = LocalDateTime.FromDateTime(unspecifiedDateTime);
    ZoneLocalMapping mapping = zone.MapLocal(local);
    // Read documentation for details of this; you can easily detect the
    // unambiguous/ambiguous/skipped cases here. You should decide what to do with them.
    ZoneInterval mappedInterval = mapping.EarlyInterval;
    TimeSpan bclOffset = mappedInterval.WallOffset.ToTimeSpan();
    return new DateTimeOff(unspecifiedDateTime, bclOffset);
}

答案 1 :(得分:1)

您可以使用新的时区偏移量创建一个新的DateTimeOffset变量吗?在您所有现有的ZonedDateTime值仅代表全局范围内的一个“真实”时间之后,如果我们考虑时间概念,则更新偏移量将更新该时间。

否则,您可以在目标时区中创建一个新的DateTimeOffset,然后使用Subtract方法修改您的现有时间。它将返回一个新的DateTimeOffset值。 像这样:https://stackoverflow.com/a/49518361/8191918