6

原来这似乎是一个复杂的主题,如果我的方法太简单,请告诉我。

基本上我要做的是在每天早上 7 点向用户列表发送电子邮件提醒(仅当他们有提醒出现时,但除此之外)。当然,早上 7 点是在不同的时间,这取决于全世界每个人的服务器位置。

计划是在用户注册时通过 javascript 从用户那里收集到 GMT 偏移时间:

var today = new Date();  
var offset = -(today.getTimezoneOffset()/60);

很简单,我现在知道偏移时间并将其与其他用户数据一起存储在数据库中。现在服务器端我设置了一个每小时运行一次的 TimerTask。我收集系统时间(比如早上 5 点),看看距离我的目标时间有多远(在本例中为 2 (7-5)),获取系统偏移小时(在本例中为 -5),然后拉数据库中所有 GMT 偏移小时为 -3 (-5 + 2) 的用户,然后发送电子邮件等。此时我假设我知道时区偏移为 -3 的每个人的早上 7 点,我可以继续该过程。这将在下一小时再次运行并收集时区偏移为 -4 的所有用户。这是真正有用的东西,还是我错过了什么?

Calendar systemTime = Calendar.getInstance();
int targetHour = 7;
int currentHour = systemTime.get(Calendar.HOUR_OF_DAY); //Its 5 am.
int difference = targetHour - currentHour; //2
int zoneOffset = systemTime.get(Calendar.ZONE_OFFSET) / (1000*60*60); //-5
int targetZone = zoneOffset + difference; //-3

List<User> users = userDAO.findByZoneOffset(targetZone);
for(User user : users) {
    //Send email or whatever I want to do with these users.
}

我理解客户端时区可能设置不正确并因此产生关闭结果的可能性,但我愿意冒这个风险,因为提醒在早上 7 点准确发出并不是绝对必要的,只是更可取。

4

1 回答 1

1

计划是在用户注册时通过 javascript 从用户那里收集到 GMT 偏移时间

这不足以一致地获得时区。它没有考虑夏令时。因此,如果用户在任何遵守夏令时的地方,他们将在大约半年的时间里在早上 6 点收到电子邮件,或者在大约半年的时间里在早上 8 点收到电子邮件。您最好根据 IP 地理位置 + 偏移量猜测他们的时区。

我有一个每小时运行一次的 TimerTask 设置。

我建议比这更频繁地运行。否则,您很可能会发现自己在发送电子邮件之前就醒了- 所以您然后回去睡觉,并在下次 7:59 发送电子邮件......您当前的时间可能是 8:59方案,基于客户端 DST 更改。到那时,您的预定发送时间差了将近两个小时!

我收集系统时间

也不要那样做。此时需要考虑两个时区 - 您的服务器时区完全无关紧要。使用 UTC 直到您转换为客户端的本地时间。这将使生活变得更加简单。如果您仍在使用Calendar,您只需设置其时区即可。

查看您的代码,如果您按小时完全匹配进行检查,您似乎最终也可能完全错过一堆用户。如果您最终在(例如)3:59 运行一次,然后在 4:01 运行一次,那么您会错过必须在 4 点运行的任何人。我建议跟踪您上次向每个用户发送邮件的时间 -或者可能是你最后一次跑步的时候——并用它来确保你总是抓住每个人。

最后,我强烈建议您使用Joda Time。这是一个简洁的日期/时间 API,它将帮助您思考在代码中正确位置使用的正确概念。

于 2012-12-10T07:15:40.737 回答