My Java application needs to send an email out to all users once per day. I'd like to deliver it at approximately 2AM based on each user's local time. So a user in New York would get the message at 2AM America/New_York time. A user in Los Angeles would get the message at 2AM America/Los_Angeles time. My mailing process would run once each hour of the day.
I plan to use HTML5 geo-location features or IP Address geo-locating to automatically determine each user's time zone during sign up. Of course, the user can modify the timezone manually if these values are incorrect. I intend to store the selected timezone in the User object as a Timezone ID string, such as "America/New_York". This will persist to the database as a string, but this could be changed if necessary.
Things to consider:
- I need to account for daylight savings time, so the user always receives the email around 2AM. This means I can't just store GMT-8 or similar UTC offsets in the user object. Part of the year Los Angeles is in GMT-7, and other parts it is in GMT-8.
- Another SO question has answers that suggest storing offset information, but I don't see how that would work as the times in different places can change throughout the year. I'm not going to update all my user objects timezones whenever a timezone change event somewhere in the world happens.
- I am using JodaTime in my application, so I can take advantage of it if it will help.
- I'm using Hibernate for database queries and would like to find a solution that could be handled in a hibernate query, without needing to process hundreds of thousands of user records in Java.
I'm using Spring Scheduling cron features (via Quartz) to run a method at 2 minutes past the hour every hour of the day. Right now most of my users are in America/Los_Angeles, so I'm manually forcing all mail to be sent at 2:02AM Pacific time. The following method runs every hour at :02 past the hour, but it manually checks the time and only proceeds if the current time in Los Angeles is in the 2:00 hour. This means users in other places will get the email at a different time than 2AM.
@Scheduled(cron="0 2 * * * *")
public void sendDailyReportEmail() {
DateTime now = new DateTime(DateTimeZone.forID("America/Los_Angeles"));
if (now.getHourOfDay() != 2) {
log.info("Not 2AM pacific, so skipping email reports");
return;
}
// send email reports
}
So, what I need is to perform a database query that will give me all users that have a local time in the 2:00AM hour, based on the time zone in their User object. Any thoughts on how to accomplish this?