让我描绘一下我的情景:
我在位于德克萨斯州达拉斯的服务器上有一个正在运行的应用程序(我认为它在内部使用EDT时区)。在这个服务器中,我需要获取时间服务器,将其转换为欧洲/马德里时区,然后检查获得的日期是否在日期间隔内。
奇怪的是,我得到一个响应,表明当前服务器时间一旦转换到欧洲/马德里时区,就在较低的日期间隔之前,这非常奇怪。
以下是我如何做到这一点,获取服务器时间并将其转换为欧洲/马德里时区:
DateTimeZone timeZoneMadrid = DateTimeZone.forID( "Europe/Madrid" );
DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm");
DateTime nowServer = new DateTime();
log.debug("Current server time is " + nowServer.toString(formatter));
DateTime nowServerSpanishTimeZone = nowServer.withZone(timeZoneMadrid);
log.debug("Current server time converted to Madrid Zone is " + nowServerSpanishTimeZone.toString(formatter));
输出:
Current server is 2014-10-06 06:12
Current server time converted to Madrid Zone is 2014-10-06 12:12
现在,我根据转换的DateTime:
为间隔,开始和结束创建DateTimeint year = serverTimeConverted.getYear();
int month = serverTimeConverted.getMonthOfYear();
int day = serverTimeConverted.getDayOfMonth();
this.setStartDate(new DateTime(year, month, day, 8, 0, 0, 0));
this.setEndDate(new DateTime(year, month, day, 21, 0, 0, 0));
如您所见,我的间隔时间为08:00:00至21:00:00
然后我检查转换的服务器时间是否在日期范围内,这是非常冗长的,因为我添加了大量的检查和输出,因为奇怪的行为......:
private boolean withinTimeRange(DateTime now, DateTime start, DateTime end){
DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYYMMdd-HH:mm");
String currentDate = now.toString(formatter);
long nowTimeStamp = now.getMillis() / 1000;
long startTimeStamp = start.getMillis() / 1000;
long endTimeStamp = end.getMillis() / 1000;
log.debug("Checking if date " + currentDate + " is in the interval dates " + start.toString(formatter) + " and " + end.toString(formatter));
log.debug("Checking if UNIX timestamp " + nowTimeStamp + " is in the interval dates " + startTimeStamp + " and " + endTimeStamp);
if (!now.isBefore(start)){
log.debug("Current time " + currentDate + " is not before " + start.toString(formatter));
if (!now.isAfter(end)){
log.debug("Current time " + currentDate + " is not after " + end.toString(formatter));
return true;
}
else{
log.debug("Current time " + currentDate + " is after " + end.toString(formatter));
return false;
}
}
else{
log.debug("Current time " + currentDate + " is before " + start.toString(formatter));
return false;
}
}
只需调用转换时间服务器的方法以及开始和结束日期,对于上一个输出,转换的服务器时间是2014-10-06 12:12,我从以前的方法获得此输出:
Checking if date 20141006-12:12 is in the interval dates 20141006-08:00 and 20141006-21:00
Checking if UNIX timestamp 1412590332 is in the interval dates 1412596800 and 1412643600
Current time 20141006-12:12 is before 20141006-08:00
Current timeserver converted to Madrid TimeZone is not within time range, skipping iteration
正如您所看到的,转换服务器时间的时间戳是在开始日期时间之前.....这怎么可能?
我认为在创建DateTime开始和结束时我做错了什么,我尝试用.withTimeZone(" Europe / Madrid")创建它们,但后来我得到了最奇怪的行为......任何线索?
谢谢!
更新:基于之前的SO问题here,我修改了之前的代码,现在它可以正常运行:
DateTime now = new DateTime();
LocalDate today = now.toLocalDate();
LocalDate tomorrow = today.plusDays(1);
DateTimeZone timeZoneMadrid = DateTimeZone.forID( "Europe/Madrid" );
DateTime start = today.toDateTimeAtStartOfDay(timeZoneMadrid);
DateTime end = tomorrow.toDateTimeAtStartOfDay(timeZoneMadrid);
start = start.plusHours(8);
end = end.minusHours(4);
Interval interval = new Interval(start, end);
DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm");
String currentDate = now.toString(formatter);
if (interval.contains(now)){
return true;
}
else{
return false;
}
答案 0 :(得分:3)
方法DateTime::getMillis
返回毫秒,与zone无关。该值是常数
创建DateTime
实例后,将在任何时区返回相同的毫秒数。
final DateTime now = DateTime.now();
now.withZone(texas).getMillis() == now.withZone(madrid).getMillis(); // true
DateTime::isAfter
和DateTime::isBefore
方法比较DateTime::getMillis
方法返回的毫秒数
所以这个值也是区域独立的。
但使用DateTime
打印DateTimeFormatter
与区域有关。它将在不同的时区打印不同的小时/分钟。
因此,如果您想独立比较日期区域,那么您的结果是正确的。
示例:强>
- 前提条件:
DateTimeZone usZone = DateTimeZone.forID("US/Eastern");
DateTimeZone spZone = DateTimeZone.forID("Europe/Madrid");
DateTimeZone.setDefault(usZone);
您的代码以下一种方式运作:
DateTime serverDate = new DateTime(2014, 10, 6, 6, 12); // US zone
DateTime dateInMadrid = serverDate.withZone(spZone); // zone is Madrid, but .getMillis() will return the same value
DateTime startDate = new DateTime(2014, 10, 6, 8, 0); // US zone
// startDate = startDate.withZone(spZone) - this will not change the result
DateTime endDate = new DateTime(2014, 10, 6, 21, 0); // US zone
// endDate = endDate.withZone(spZone) - this will also not change the result
System.out.println(dateInMadrid .isAfter(startDate) && dateInMadrid .isBefore(endDate));
// false - it is correct. because all dates were created in US zone
正确的方法:您应该在马德里区创建start
和end
日期
DateTime serverDate = new DateTime(2014, 10, 6, 6, 12);
DateTime startDateMadrid = new DateTime(2014, 10, 6, 8, 0, spZone); // Madrid zone is used in constructor!
DateTime endDateMadrid = new DateTime(2014, 10, 6, 21, 0, spZone); // Madrid zone is used in constructor!
System.out.println(serverDate.isAfter(startDateMadrid) && serverDate.isBefore(endDateMadrid));
// true