如何从NodaTime中的偏移获取所有IANA时区

本文关键字:获取 IANA 时区 NodaTime | 更新日期: 2023-09-27 18:20:36

在我们的ASP.NET MVC 5应用程序中,我们有带有时区ID(IANA)的用户配置文件。

public class User
{
    public int Id { get; set; }
    public string TimeZoneId { get; set; }
}

任务是在当地时间早上6点向所有用户发送一封电子邮件。我们的计划是每小时向当地时间为该时间点早上6点的所有时区发送电子邮件(根据服务器的UTC时间计算)。

由于我们只有时区ID,我希望获得相应的时区ID,比如说,偏移量-4:00:00-,同时考虑DST

string[] timezoneIds;

然后我可以这样查询我的数据库:

db.Users.Where(x => timezoneIds.Contains(x.TimeZoneId));

很明显,我的问题是,这是一个不错的想法,还是有我不知道的解决这个问题的最佳实践?

谢谢。

如何从NodaTime中的偏移获取所有IANA时区

;建立字典";Serge显示:使用LINQ的查找、DateTimeZone.GetUtcOffsetOffset密钥,而不是TimeSpan值:

var now = SystemClock.Instance.GetCurrentInstant();
var provider = DateTimeZoneProviders.Tzdb;
var idsByCurrentOffset = provider.Ids.ToLookup(id => provider[id].GetUtcOffset(now));

然后你可以使用:

var offset = Offset.FromHours(5);
foreach (var id in idsByCurrentOffset[offset])
{
    ...
}

(您甚至不需要先检查是否存在,因为当出现查找中不存在的键时,查找索引器会返回一个空序列。)

您可以尝试以下操作:

首先创建一个字典,其中包含所有偏移和属于该偏移的时区

Instant now = SystemClock.Instance.Now;
IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
Dictionary<TimeSpan, List<string>> timezonesForOffset = new Dictionary<TimeSpan, List<string>>();
foreach(var id in timeZoneProvider.Ids){
    ZonedDateTime zdt = now.InZone(timeZoneProvider[id]);
    var timespan = zdt.Offset.ToTimeSpan();
    if(timezonesForOffset.ContainsKey(timespan)){
        timezonesForOffset[timespan].Add(id);
    } else {
        timezonesForOffset[timespan] = new List<string> {id, };
    }
}

完成后,您可以使用以下代码段获取特定时区内的所有用户

var timespan2 = new TimeSpan(1,0,0);
var timezonesWithOffset = timezonesForOffset[timespan2];
var usersinTimezone = db.Users.Where(x=> timezonesWithOffset.Contains(x.TimezoneId)).ToList();

这将使时区utc+1 中的所有用户