In our ASP.NET MVC 5 application we have user profiles with a Timezone ID (IANA).
public class User
{
public int Id { get; set; }
public string TimeZoneId { get; set; }
}
The task is to send all users an email at 6 AM local time. Our plan is to send out emails every hour to all timezones where the local time is 6 AM at that point in time (calculated based on the UTC time of the server).
Since we only have the Timezone ID to go by, I was hoping to get the corresponding Timezone IDs for, let's say, offset -4:00:00 -- taking into account DST.
string[] timezoneIds;
I could then query my database like so:
db.Users.Where(x => timezoneIds.Contains(x.TimeZoneId));
My question is, obviously, is this a decent idea or are there best practices for this problem that I am not aware of?
Thanks.
Simpler code for the "building a dictionary" that Serge shows: use LINQ's lookup, DateTimeZone.GetUtcOffset
, and Offset
keys instead of TimeSpan
values:
var now = SystemClock.Instance.GetCurrentInstant();
var provider = DateTimeZoneProviders.Tzdb;
var idsByCurrentOffset = provider.Ids.ToLookup(id => provider[id].GetUtcOffset(now));
Then you can use:
var offset = Offset.FromHours(5);
foreach (var id in idsByCurrentOffset[offset])
{
...
}
(You don't even need to check for existence first, as the lookup indexer returns an empty sequence when presented with a key that doesn't exist in the lookup.)
You could try the following:
First create a dictionary with all the offsets and the timezones belonging to that 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, };
}
}
After you have done that you could use the following snippet to get all users within a certain timezone
var timespan2 = new TimeSpan(1,0,0);
var timezonesWithOffset = timezonesForOffset[timespan2];
var usersinTimezone = db.Users.Where(x=> timezonesWithOffset.Contains(x.TimezoneId)).ToList();
That would get all users in the timezone utc+1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With