gpt4 book ai didi

java - 根据用户的本地时区在特定时间执行日常操作

转载 作者:搜寻专家 更新时间:2023-10-31 20:31:02 34 4
gpt4 key购买 nike

我的 Java 应用程序需要每天向所有用户发送一封电子邮件。我想根据每个用户的本地时间在凌晨 2 点左右送达。因此,纽约的用户会在美国/纽约时间凌晨 2 点收到消息。洛杉矶的用户将在美国/洛杉矶时间凌晨 2 点收到消息。我的邮寄流程将在一天中每小时运行一次。

我计划在注册期间使用 HTML5 地理定位功能或 IP 地址地理定位来自动确定每个用户的时区。当然,如果这些值不正确,用户可以手动修改时区。我打算将选定的时区作为时区 ID 字符串存储在用户对象中,例如“America/New_York”。这将作为字符串保存到数据库中,但如果需要可以更改。

需要考虑的事项:

  • 我需要考虑夏令时,因此用户总是在凌晨 2 点左右收到电子邮件。这意味着我不能只在用户对象中存储 GMT-8 或类似的 UTC 偏移量。洛杉矶一年中的部分时间使用 GMT-7,其他时间使用 GMT-8。
  • Another SO question有建议存储偏移量信息的答案,但我不知道这将如何工作,因为不同地方的时间全年都会发生变化。我不会在世界某个地方发生时区更改事件时更新我所有的用户对象时区。
  • 我在我的应用程序中使用 JodaTime,所以如果它有帮助,我可以利用它。
  • 我正在使用 Hibernate 进行数据库查询,并希望找到一种可以在 Hibernate 查询中处理的解决方案,而无需在 Java 中处理数十万条用户记录。

我正在使用 Spring Scheduling cron 功能(通过 Quartz)在一天中的每小时整点过 2 分钟运行一个方法。现在我的大部分用户都在美国/洛杉矶,所以我手动强制所有邮件在太平洋时间凌晨 2:02 发送。以下方法每小时在整点 :02 运行,但它会手动检查时间,并且仅当洛杉矶的当前时间在 2:00 时才会继续。这意味着其他地方的用户将在不同于凌晨 2 点的时间收到电子邮件。

@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
}

因此,我需要执行一个数据库查询,该查询将根据用户对象中的时区为我提供本地时间为凌晨 2:00 的所有用户。关于如何实现这一点有什么想法吗?

最佳答案

我对此进行了更多思考并找到了可能的解决方案。我还没有实现它,但我认为它应该可以工作。基本上,它涉及执行以下查询(注意:这是特定于 MySQL 的):

select * from members where hour(convert_tz(now(),'UTC',timezone)) = 3;

此查询通过执行以下操作选择当前本地时间在凌晨 3 点到凌晨 3:59 之间的所有成员:

  1. 它使用 now() 获取当前服务器时间,这是 UTC 时间,因为数据库服务器配置为 UTC 时间。
  2. 然后使用 convert_tz() 函数将该时间转换为成员表的 timezone 列中指定的成员时区。请注意,Member 类包含格式为“America/Los_Angeles”的时区字段。
  3. 接下来,它使用 hour() 函数检查现在是几点,看是否是 3,即凌晨 3 点。
  4. 查询然后返回满足这些要求的所有成员,并向他们每个人发送电子邮件。

我有点担心每小时为系统中的每个成员进行时区转换和计算。我将不得不进行测试,看看它给数据库带来了什么样的负载,但它可能会因数百万甚至 10k 的用户而窒息。

一个可以显着减轻负载但不那么优雅的替代方法是执行以下操作(注意此代码未经测试!):

@Scheduled(cron="0 2 * * * *")
public void sendDailyReportEmail() {

Query query = session.createQuery(
"select distinct m.timezone from Member m");
List<String> timezones = query.list();

for (String timezone : timezones) {
DateTime now = new DateTime(DateTimeZone.forID(timezone));
if (now.getHourOfDay() == 3) {
Query query2 = session.createQuery(
"from Member where timezone = :zone");
query2.setParameter("zone", timezone);
List<Member> members = query2.list();
// send email reports
}
}
}

此代码执行此操作:

  1. 在整点后 2 分钟执行方法,每天每小时
  2. 在数据库中查询成员表中所有唯一时区的列表。
  3. 对于找到的每个时区,确定它当前是否在凌晨 3 点。
  4. 如果时区是凌晨 3 点,请选择该时区的所有成员并向他们发送电子邮件。

这会在每小时开始时增加一点额外开销,但不需要针对每个用户的时区处理。系统实际使用的唯一时区可能只有几十个。我不太可能在所有 500 多个时区都有成员。

最后一件事。我没有在凌晨 2 点发送电子邮件,而是将其移至凌晨 3 点。这是因为 Spring 夏令时更改时,时间从凌晨 2 点更改为凌晨 3 点。所以没有凌晨 2:02 这样的事情,这意味着那天不会发送电子邮件。此外,在秋天,系统可以向每个用户发送 2 封电子邮件,因为一个小时会重复。我需要查明非美国时区是否会在不同时间更改时间,因为凌晨 3 点可能在其他地方是个问题。

关于java - 根据用户的本地时区在特定时间执行日常操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3706938/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com