Получить список часовых поясов для данного смещения в минутах, используя 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);
        }
    }
}
Другие вопросы по тегам