我在java中有一个关于区域的问题。 我有一个用户案例,用户可以设置时区和一些时间表。例如,周一和周日晚上11点运行任务,时区为America / Los_Angeles。 如果我的服务器时区是UTC + 0:00我有一个问题如何正确检测星期几和新时间(它将在周二和周一早上6点)。所以我的问题是如何根据服务器时区和用户时区正确运行用户任务。
更新
我有一个cron表达式,我可以设置小时,分钟和星期几。 当用户创建新任务时,他可以设置自定义时区(例如,使用自定义时区UTC-7:00在星期一晚上11点运行任务) 因此,如果我的理解是正确的,我需要将他的小时设置(晚上11点)转换为相应的服务器时间。因此,如果我的服务器时区是UTC + 3:00,我需要将晚上11点转换为上午9点,而不是我的服务器上的周一(但周二)。然后,如果我将在周二上午9点运行cron,它将在周一晚上11点向用户查找任务运行。我的方法是否正确?我希望你理解我的问题。提前谢谢。
答案 0 :(得分:0)
简答:自纪元以来以毫秒为单位计算。
答案很长:
首先,了解计算机时间如何工作非常重要。我会建议this article。,但要点是,所有事情都是在自1990年1月1日的时代以来计算出来的。其次,我想一个例子会告诉你超过1000个单词:
var sendSearch = true;
var isTiming = false;
var timeout = 300;
$("#s_search").on("keyup", function(){
if (!isTiming){
isTiming = true;
setInterval(function(){sendSearch = true;}, timeout);
}
if (sendSearch){
sendSearch = false;
// do your ajax post here
}
});
ZonedDateTime将始终使用UTC(+ 0)加上定义的时区。
编辑(更新后):
是的,如果您获得了用户设置的时间和时区,则必须将其转换为您自己的时区,以便在同一时间点执行。
答案 1 :(得分:0)
服务器操作系统和JVM的时区设置应与您的编程无关。两者都可以在运行时期间随时更改,因此不要依赖它。 始终在各种日期时间方法的可选参数中指定所需/预期的时区。
请注意,您无法提前安排时区敏感时刻。政治家因经常改变时区定义而臭名昭着,有时很少提前通知。
如果要在用户时区的上下文中为下周一上午11点设置闹钟,首先需要用户的时区。您可能能够检测到默认时区,但最终唯一可靠的方法是询问用户所需的/预期时区。
以continent/region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
将闹钟的星期几保持为DayOfWeek
枚举对象。
DayOfWeek alarmDow = DayOfWeek.MONDAY ;
将闹钟的时间保持为LocalTime
。
LocalTime alarmTimeOfDay = LocalTime.parse( "11:00:00" );
此课程缺少日期,缺少任何来自UTC或时区的偏移。所以在你调整到一个时区之前没有任何意义。
将闹钟的时区保持为ZoneId
。
ZoneId z = ZoneId.of( "America/Montreal" );
掌握这些部件后,您可以安排闹钟。
以Instant
获取当前时刻。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。
Instant now = Instant.now();
应用所需的时区以获得ZonedDateTime
。
ZonedDateTime zdtNow = instant.atZone( z );
要确定警报的未来时刻,请使用TemporalAdjuster
界面操作日期时间值。类TemporalAdjusters
(注意复数s
)提供了实现。首先提取一个仅限日期的值,因为我们将报警的LocalTime
指定为时间。
LocalDate today = zdtNow.toLocalDate();
LocalDate dateOfNextOrSameDow = today.with( TemporalAdjusters.withNextOrSame( alarmDow ) );
应用所需的时间。
ZonedDateTime zdtAlarm = ZonedDateTime.of( dateOfNextOrSameDow , alarmTimeOfDay , z ) ;
此特定警报日期时间可能已于今天早些时候通过。所以考试。如果是这样,请添加一周以获得所需的星期几的下一次出现。
if( zdtAlarm.isBefore( zdtNow ) ) { // If already passed…
zdtAlarm = zdtAlarm.plusWeeks( 1 ); // …go to next day-of-week occurrence.
}