Java 每天在同一时间向不同时区发送电子邮件

Posted

技术标签:

【中文标题】Java 每天在同一时间向不同时区发送电子邮件【英文标题】:Java Sending Email to Different Time Zones At the Same Time Each Day 【发布时间】:2012-11-27 14:25:39 【问题描述】:

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

基本上,我要做的是在每天早上 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 点准确发出并不是绝对必要的,只是更可取。

【问题讨论】:

【参考方案1】:

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

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

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

我建议多跑几次。否则,您很可能会发现自己就在发送电子邮件之前醒来了 - 所以你又回去睡觉,并在下次 7:59 发送电子邮件......这可能根据客户端 DST 更改,使用您当前的方案是 8:59。到那时,您的预定发送时间已经差了将近两个小时!

我收集系统时间

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

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

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

【讨论】:

关于夏令时的整个 GMT 偏移量我有点困惑。例如,我在北卡罗来纳州的时区是-5,据我所知,全年都不会改变,不是吗?如果我要在春天检查,它实际上会是-4吗?我想通过使用系统时钟它会自动调整为 DST。再说一次,世界上的某些地方根本不使用 DST,所以我猜当服务器处于 DST 时,它会计算出不正确的时间......错误..时区。 @ryandlf:我不具体了解北卡罗来纳州,但美国大部分地区都遵守夏令时。你每年春天和秋天都会更换时钟吗?如果是这样,那就是改变 UTC 偏移量。请注意,您碰巧运行服务器的任何地方的系统时钟都可能会在不同日期向用户更改 DST。哎呀,它很容易改变方向(因为南半球在相反方向观察DST,例如将他们的时钟向后在〜三月一个小时,然后把他们向前 1 小时 ~10 月)。或者其他国家/地区有非常不同的 DST 转换。 你知道根据ip geo收集时区的资源吗?我找不到任何示例。 @ryandlf:我建议你搜索“检测时区 javascript”或类似的东西。基本上这是一个相当复杂的业务。当然,一种选择是询问用户。进行猜测,但允许用户更改他们的设置。

以上是关于Java 每天在同一时间向不同时区发送电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

在电子邮件正文中发送带有动态内容的图像

Joomla 3.3 模块不向不同域发送电子邮件

UTC 时间、时区、夏令时和夏令时切换日期

如何在 PHP 中向用户发送每日电子邮件通知?

使服务器每天运行一次

如何使用 Mailchimp API 3.0 多次向订阅者发送同一封电子邮件