Получить список часовых поясов для данного смещения в минутах, используя Noda Time
Я пытаюсь спроектировать следующее решение для часового пояса с использованием Noda Time:
Пользователь может использовать мобильное приложение или веб-приложение для входа в систему. Во время входа в систему веб-API будет вызываться со смещением от UTC (скажем, х минут) в качестве параметра.
Теперь, если смещение (х минут) отличается от смещения (и часового пояса), сохраненного в базе данных, тогда пользователю будет показан список часовых поясов, которые находятся на расстоянии х минут от UTC, чтобы он мог выбрать один из них. Выбранный часовой пояс и соответствующее смещение (х минут) будут сохранены в базе данных как последний часовой пояс пользователя.
Как я могу получить список часовых поясов, которые находятся на расстоянии х минут от UTC, используя Noda Time?
Например, если пользователь находится на расстоянии +330 минут от UTC, он получит следующее приглашение:
Мы обнаружили, что вы на 5 часов 30 минут опережаете время по Гринвичу. Пожалуйста, выберите текущий часовой пояс: "Азия / Коломбо", "Азия / Калькутта"
2 ответа
Вы можете сделать что-то вроде этого:
TimeZoneInfo.GetSystemTimeZones()
.Where(x => x.GetUtcOffset(DateTime.Now).TotalMinutes == 330)
И теперь у вас есть коллекция часовых поясов! Вы можете заменить DateTime.Now
с какой-то другой датой или DateTimeOffset
в зависимости от вашей ситуации.
В Noda Time вы можете сделать это:
using NodaTime;
using NodaTime.TimeZones;
TzdbDateTimeZoneSource.Default.GetIds()
.Select(x => TzdbDateTimeZoneSource.Default.ForId(x))
.Where(x =>
x.GetUtcOffset(SystemClock.Instance.GetCurrentInstant()).ToTimeSpan().TotalMinutes == 330)
Несколько альтернативный подход к коду Sweeper, использующий целевое смещение вместо преобразования каждого смещения в TimeSpan
используя одно вычисление "сейчас" (для согласованных результатов) и используя IDateTimeZoneProvider.GetAllZones
метод расширения.
using System;
using System.Linq;
using NodaTime;
using NodaTime.Extensions;
class Test
{
static void Main()
{
// No FromMinutes method for some reason...
var target = Offset.FromSeconds(330 * 60);
var now = SystemClock.Instance.GetCurrentInstant();
var zones = DateTimeZoneProviders.Tzdb.GetAllZones()
.Where(zone => zone.GetUtcOffset(now) == target);
foreach (var zone in zones)
{
Console.WriteLine(zone.Id);
}
}
}