【发布时间】:2015-06-09 13:29:40
【问题描述】:
我需要根据用户提供的两个字符串创建一个新的 Java Date:日期(例如“1.1.2015”)和一天中的时间(例如“23:00”)。首先,用户输入日期,该日期被发送到服务器并解析为Date(一天中的时间设置为用户所在时区的午夜)。在此之后,用户输入发送到服务器的时间,并且需要创建一个新的Date,结合来自第一个Date 实例的日期和来自新用户输入的时间。
示例:假设服务器的时区是 UTC,而用户的时区是 UTC-2。用户在日期字段中输入“1.1.2015”,在服务器中将其解释为 2:00 1.1.2015 UTC(UTC 时间 1 月 1 日凌晨 2:00,即用户时区的午夜)。然后用户在时间字段(24 小时制)中输入“23:00”。这需要在服务器中解释为 1:00 2.1.2015 UTC(1 月 2 日凌晨 1:00)。
我们使用 Apache Commons FastDateFormat 将字符串转换为 Dates,反之亦然,并使用 Joda Time 进行日期操作。结果需要是一个普通的旧 Java 日期。我尝试将现有的 Date 实例和用户输入的时间结合起来,如下所示:
Date datePart= ...; // The date parsed from the first user input
FastDateFormat timeFormat = ...;
DateTimeZone userTimeZone = DateTimeZone.forTimeZone(timeFormat.getTimeZone());
String userTimeInput = ...; // The time of day from the user
MutableDateTime dateTime = new MutableDateTime(datePart, DateTimeZone.UTC);
Date newTime = timeFormat.parse(userTimeInput);
dateTime.setTime(new DateTime(newTime, DateTimeZone.UTC));
// Determine if the date part needs to be changed due to time zone adjustment
long timeZoneOffset = userTimeZone.getOffset(dateTime);
long newMillisOfDay = dateTime.getMillisOfDay();
if (newMillisOfDay + timeZoneOffset > 24 * 60 * 60 * 1000) {
dateTime.addDays(-1);
} else if (newMillisOfDay + timeZoneOffset < 0) {
dateTime.addDays(1);
}
Date newServerDate = dateTime.toDate();
像这样更改现有Date 的时间有点问题。以上不起作用;如果用户多次更改一天中的时间,则可能每次都进行 +/-1 天的调整。另外,上面的代码没有考虑夏令时。如果datePart 是 DST,我们的示例用户输入的时间应该被视为 UTC-1。当使用FastDateFormat 并且只解析一天中的时间时,日期设置为纪元,这意味着用户输入的时间将始终被视为UTC-2。这将导致结果偏移一小时。
如何根据给定时间调整服务器中的Date,并适当考虑时区和夏令时?
【问题讨论】:
-
说实话,您的意思并不是很清楚 - 但您知道
Date对象只是一个时间点吗?它没有任何时区的概念。原始的Date对象是什么意思?如果由于时区的原因,Date对象最终对用户意味着与服务器上不同的日期(即天),您会发生什么?字符串从哪里来?如果您能更清楚地了解输入、预期输出和您获得的实际输出,将会有所帮助。 -
是的,我知道
Date没有时区。我修改了我的问题以使其更清楚。 -
听起来一切都是在用户的时区完成的——那么为什么服务器的时区会起作用呢?请注意,“用户时区的午夜”并不总是存在,请注意。将日期解析为
LocalDate并保留 that 而不是Date会好得多。我还建议不要使用MutableDateTime,如果您已经在使用 Joda Time,为什么还要使用FastDateFormat?理想情况下,始终只使用 Joda Time,但如果您必须使用Date,至少尽可能使用 Joda Time。 (顺便说一句,我们仍然看不到示例输入/输出...
标签: java date jodatime apache-commons-lang