Как изменить Timzone для ZonedDateTime без преобразования времени - PullRequest
1 голос
/ 18 июня 2019

У меня есть ZonedDateTime, который я создал, используя DateTimeOffset и идентификатор часового пояса (строка), и у меня также есть DateTimeZone.

В конкретном случае у меня есть необходимость изменить Zone ZonedDateTime без фактического преобразования времени (т.е. у меня 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 ]

5 голосов
/ 20 июня 2019

Как указано в комментариях, желание сделать это обычно указывает на то, что что-то сломано в последующем - и если вы можете исправить это там, вам следует.

Если вы окажетесь в ситуации с 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 голос
/ 19 июня 2019

Можете ли вы создать новую переменную DateTimeOffset с новым смещением часового пояса? после того, как все ваши существующие ZonedDateTime значения просто представляют одно «истинное» время через глобальное, обновление смещения обновит время, которое является правильным, если мы думаем о концепции времени.

В противном случае вы можете создать новый DateTimeOffset в целевом часовом поясе, а затем использовать метод Subtract, чтобы изменить существующее время. он вернет новое значение DateTimeOffset. Как это: https://stackoverflow.com/a/49518361/8191918

...