Как мне заполнить список часовых поясов IANA / Olson от Noda Time?

Я использую NodaTime в приложении, и мне нужно, чтобы пользователь выбирал свой часовой пояс из выпадающего списка. У меня есть следующие мягкие требования:

1) Список содержит только варианты, которые разумно действительны для настоящего и ближайшего будущего для реальных мест. Необходимо отфильтровать исторические, неясные и общие часовые пояса.

2) Список должен быть отсортирован сначала по смещению UTC, а затем по названию часового пояса. Это, надеюсь, ставит их в порядок, который имеет смысл для пользователя.

Я написал следующий код, который действительно работает, но не имеет того, что мне нужно. Вероятно, фильтр необходимо отрегулировать, и я предпочел бы, чтобы смещение представляло собой смещение базы (не-dst), а не текущее смещение.

Предложения? Рекомендации?

var now = Instant.FromDateTimeUtc(DateTime.UtcNow); var tzdb = DateTimeZoneProviders.Tzdb; var list = from id in tzdb.Ids where id.Contains("/") && !id.StartsWith("etc", StringComparison.OrdinalIgnoreCase) let tz = tzdb[id] let offset = tz.GetOffsetFromUtc(now) orderby offset, id select new { Id = id, DisplayValue = string.Format("({0}) {1}", offset.ToString("+HH:mm", null), id) }; // ultimately we build a dropdown list, but for demo purposes you can just dump the results foreach (var item in list) Console.WriteLine(item.DisplayValue); 

Noda Time 1.1 имеет данные zone.tab , поэтому теперь вы можете сделать следующее:

 ///  /// Returns a list of valid timezones as a dictionary, where the key is /// the timezone id, and the value can be used for display. ///  ///  /// The two-letter country code to get timezones for. /// Returns all timezones if null or empty. ///  public IDictionary GetTimeZones(string countryCode) { var now = SystemClock.Instance.Now; var tzdb = DateTimeZoneProviders.Tzdb; var list = from location in TzdbDateTimeZoneSource.Default.ZoneLocations where string.IsNullOrEmpty(countryCode) || location.CountryCode.Equals(countryCode, StringComparison.OrdinalIgnoreCase) let zoneId = location.ZoneId let tz = tzdb[zoneId] let offset = tz.GetZoneInterval(now).StandardOffset orderby offset, zoneId select new { Id = zoneId, DisplayValue = string.Format("({0:+HH:mm}) {1}", offset, zoneId) }; return list.ToDictionary(x => x.Id, x => x.DisplayValue); } 

Альтернативный подход

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

введите описание изображения здесь

Получить стандартное смещение легко – tz.GetZoneInterval(now).StandardOffset . Это даст вам «текущее» стандартное смещение (возможно изменение зоны со временем).

Фильтрация может быть уместна для вас – я не хотел бы говорить точно. Это, конечно, не идеальный вариант, поскольку идентификаторы не предназначены для отображения. В идеале вы использовали бы «примеры» Unicode CLDR, но на данный момент у нас нет интеграции CLDR на этом фронте.

  • Как использовать TimeZoneInfo для получения местного времени во время летнего времени?
  • Как получить текущий часовой пояс MySQL?
  • Как получить текущую дату и время вашего часового пояса в Java?
  • Преобразование временной зоны
  • Получение системных часовых поясов на разных языках
  • Как получить часовой пояс из местоположения с использованием координат широты и долготы?
  • Сокращения временной зоны
  • Как справиться с летней экономией, используя TimeZone в Java
  • Получение даты с на несколько часов
  • Список идентификаторов Timezone для использования с FindTimeZoneById () в C #?
  • .NET DateTime.Now возвращает неправильное время, когда изменяется часовой пояс
  • Давайте будем гением компьютера.