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)
正如评论中所指出的那样,通常希望在上游进一步破坏某些内容-如果可以在此处进行修复,则应该这样做。
如果最终遇到的情况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)