How to change the Timzone of a ZonedDateTime without converting the time

phi*_*ilr 1 .net c# datetime datetimeoffset nodatime

I have a ZonedDateTime which I have created using a DateTimeOffset and a timezone id (string), and I also have a DateTimeZone.

The particular case I have is that I need to change the Zone of the ZonedDateTime without actually converting the time (i.e. i have 18:00 UTC-4:00, i want to change this to 18:00 UTC-8 without converting the 18:00 accordingly)

The only pertinent function I'm finding is .WithZone(DateTimeZone) but this seems to convert my time based on the provided zone

How can I change the "timezone" of my ZonedDateTime without converting the time?

EDIT i found a solution that seems to work:

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();
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 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);
}
Run Code Online (Sandbox Code Playgroud)