【问题标题】:How to change a Date based on time-only input and account for time zone and DST?如何根据仅时间输入更改日期并考虑时区和 DST?
【发布时间】: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


【解决方案1】:

我通过使用 cmets 中 Jon 的建议解决了这个问题。我仍然必须得到一个Date,所以我不能开始使用 Joda Time 来处理所有事情。然而,对于这个特定的用例,我确实远离了 FastDateFormat 和 MutableDateTime。感谢您的提示!解决方案如下所示:

Date datePart= ...;           // The date parsed from the first user input
String userTimeInput = ...;   // The time of day from the user
Locale userLocale = ...;
DateTimeZone userTimeZone = ...;

DateTime dateInUserTimeZone = new DateTime(datePart, userTimeZone);
DateTimeFormatter formatter = DateTimeFormat.shortTime().withLocale(userLocale);
LocalTime time = formatter.parseLocalTime(userTimeInput);

Date newDate = dateInUserTimeZone.withTime(time.getHourOfDay(), time.getMinuteOfHour(),
        time.getSecondOfMinute(), time.getMillisOfSecond()).toDate();

【讨论】:

    猜你喜欢
    • 2015-03-16
    • 1970-01-01
    • 2015-03-18
    • 2018-02-22
    • 1970-01-01
    • 2014-11-19
    • 2010-11-06
    • 1970-01-01
    • 2017-05-24
    相关资源
    最近更新 更多