2015-11-05 84 views
3

在我們的ASP.NET MVC 5應用程序中,我們擁有帶有時區ID(IANA)的用戶配置文件。如何從NodaTime的偏移量中獲取所有IANA時區?

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

任務是在當地時間早上6點向所有用戶發送電子郵件。我們的計劃是每小時向當地時間早上6點(根據服務器的UTC時間計算)的所有時區發送電子郵件。

由於我們只有時區ID才能通過,因此我希望得到相應的時區ID,例如,考慮到DST,可以獲得偏移量-4:00:00 -

string[] timezoneIds; 

然後我可以查詢我的數據庫,像這樣:

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

我的問題是,很明顯,這是一個不錯的主意,或是否有針對此問題的最佳做法,我不知道呢?

謝謝。

回答

3

你可以嘗試以下方法:

首先創建一個字典,所有的偏移和屬於該時區偏移

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

內的用戶爲
+0

這種方法很好,但考慮屬特德SQL可能相當大,取決於匹配的時區數量。另外,如果代碼提前運行,那麼一定要在實際執行時間內傳遞正確的「即時」,而不是「現在」。 –

+0

噢,我相信它可以和字典中的Offset'鍵一樣使用,而不是它真的很重要。 ;) –

6

簡單的代碼了 「建設一個字典」,塞爾顯示:使用LINQ的查找,DateTimeZone.GetUtcOffset,並Offset鍵,而不是TimeSpan值:

var now = SystemClock.Instance.Now; 
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]) 
{ 
    ... 
} 

(你甚至不需要首先檢查存在性,因爲查找索引器在返回一個空序列時,如果在查找中不存在一個鍵時出現)。