【问题标题】:problems with java.util.Calendar and timeZonesjava.util.Calendar 和 timeZones 的问题
【发布时间】:2012-05-04 22:28:14
【问题描述】:

我有以下方法可以将我的自定义 DMY(日期、月份、年份)对象转换为日期。

public static Date serverCreateDateFromDMY(DMY pDMY, TimeZone pTimeZone)
    {
        Calendar vCalendar = Calendar.getInstance(pTimeZone);
        vCalendar.set(Calendar.YEAR, pDMY.getYear());
            // Below line is because DMY month counts are 1-indexed
            // and Date month counts are 0-indexed
        vCalendar.set(Calendar.MONTH, pDMY.getMonthOfYear() - 1);
        vCalendar.set(Calendar.DAY_OF_MONTH, pDMY.getDayOfMonth());
        System.out.println(vCalendar.getTime());
        TimeUtilsServer.zeroCalendarHoursAndBelow(vCalendar);
        System.out.println(vCalendar.getTime());
        return vCalendar.getTime();
    }


public static void zeroCalendarHoursAndBelow(Calendar pToZero)
    {
        pToZero.set(Calendar.HOUR_OF_DAY, 0);
        pToZero.set(Calendar.MINUTE, 0);
        pToZero.set(Calendar.SECOND, 0);
        pToZero.set(Calendar.MILLISECOND, 0);
    }

到 serverCreateDateFromDMY() 方法,我传递这些参数:DMY=20120424,时区是:America/New_York。应用程序在我的 IST 时区本地运行。

根据上述输入,打印以下输出。

Tue Apr 24 14:43:07 IST 2012

Tue Apr 24 09:30:00 IST 2012

如您所见,在最后一个输出中,时间并未归零。请问有什么建议吗?

@Marko,是的,我了解了 DateFormat,并尝试了以下示例。但日期仍然打印有时间而不是归零。

TimeZone tz = TimeZone.getTimeZone("America/New_York");
        Calendar vCalendar = Calendar.getInstance(tz);
        vCalendar.set(Calendar.YEAR, 2012);

        vCalendar.set(Calendar.MONTH, 4 - 1);
        vCalendar.set(Calendar.DAY_OF_MONTH, 24);
        DateFormat df = DateFormat.getDateTimeInstance();
        df.setTimeZone(tz); 
        System.out.println(df.format(vCalendar.getTime()));

         vCalendar.set(Calendar.HOUR_OF_DAY,     vCalendar.getActualMinimum(Calendar.HOUR_OF_DAY));
        vCalendar.set(Calendar.MINUTE, vCalendar.getActualMinimum(Calendar.MINUTE));
        vCalendar.set(Calendar.SECOND, vCalendar.getActualMinimum(Calendar.SECOND));
        vCalendar.set(Calendar.MILLISECOND,   vCalendar.getActualMinimum(Calendar.MILLISECOND));
        System.out.println(df.format(vCalendar.getTime()));

【问题讨论】:

  • TimeUtilsServer是如何实现的?

标签: java calendar timezone


【解决方案1】:

java 日期/时间 API 从创建之时起就有一个糟糕的设计。也许你应该看看一些库 - 例如隐藏 JDK API 缺陷的库 - http://joda-time.sourceforge.net/

【讨论】:

  • 嗨,巴克斯。我同意你的看法。事实上,我们正在重新设计我们的产品,我们正在用 joda time 替换这个笨拙的 java Date/Time API。
【解决方案2】:

在内部,日期和日历对象以 UTC 格式存储。当您将字段设置为 0 时,日历以 UTC 更新。

当您向日历询问时间时,它会将日期转换为您想要的时区,从而产生差异。

【讨论】:

  • 日期始终采用 UTC,从不采用系统时区。
  • 日期实际上是一个绝对的时间时刻,其他类的工作是用他们认为合适的方式表示那个时刻。 Calendar 在 UTC 中更新也是不正确的——它与您构建它的 TimeZone 相关。如果您没有使用任何时区,则它是系统默认时区。无论如何,这很令人费解。
【解决方案3】:

...您比纽约时间早 9:30。您将时间设置为纽约时间午夜并将其读出为您所在区域的时间。请注意,getTime 返回一个Date,它不是时区可配置的。如果要指定打印结果的时区,则需要 DateFormat

【讨论】:

  • 谢谢马尔科。是的,我知道了。然后我使用 DateFormat 做了简单的例子,但它仍然没有打印零时间的日期。我在评论中有字符限制,所以我不能在这里发布整个示例。
  • 最好的方法是更新您的问题以反映您的新工作,包括代码和新的不正确行为。对于上下文,您可以将其添加到底部并使用 UPDATE 为其命名。
  • 是的,我已经更新了我的问题并添加了我所做的小例子。它在 2012 年 4 月 24 日上午 6:13:13 2012 年 4 月 24 日上午 12:00:00 之后打印
  • 这实际上是正确的输出。让您感到困惑的可能只是使用美国 AM/PM 系统的默认日期格式。此输出确实以 24 小时格式表示 00:00。有关指定日期格式的信息,请参阅 SimpleDateFormat 中的 Javadoc。
  • 是的,Marko,使用 SimpleDateFormat 最终给了我正确的显示。感谢您的反馈意见。这是我使用的格式。 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss , zzzz"); sdf.setTimeZone(tz);
猜你喜欢
  • 2011-09-24
  • 1970-01-01
  • 2011-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 2013-10-26
  • 2018-07-19
相关资源
最近更新 更多