【问题标题】:Date getTime() from Calendar in specific timezone特定时区日历中的日期 getTime()
【发布时间】:2014-10-04 15:44:04
【问题描述】:

我有以下代码:

Date now = CalendarUtils.getCalendar(getDefaultTimeZone())
                .getTime();

CalendarUtils 类有以下方法

public static Calendar getCalendar(final TimeZone tz) {
    return getCalendar(CalendarUtils.getDate(), tz);
}

public static Calendar getCalendar(final Date time, final TimeZone tz) {
    final GregorianCalendar calendar = new GregorianCalendar();
    calendar.setTimeZone(tz);
    calendar.setTime(time);
    return calendar;
}

public static Date getDate() {
    return CalendarUtils.getDate(System.currentTimeMillis());
}

其中 getDefaultTimeZone() 返回特定时区中的时区对象。比如说欧洲/马德里。

但是,我的应用程序正在罗马的服务器上运行。

问题是上面的代码是用来获取马德里当地时间的。因此,8 月 8 日罗马的上午 12:30 仍然是马德里的 8 月 7 日晚上 11:30。

当我使用时

Date startOfDay = DateUtils.truncate(now, Calendar.DATE);

我希望 8 月 7 日 00:00:00 而不是 8 月 8 日 00:00:00

我已经阅读了 Date 如何从 Epoch 返回 Millis,但我希望它会从我从日历中询问的日期的 Epoch 返回 Millis。

当我在罗马时间 8 月 8 日凌晨 12:30 使用以下查询时,利用两个日期(现在和 startOfDay)我得到了 8 月 8 日而不是 7 日(马德里当地时间)的结果。

 public BigInteger getSumForDates(Date fromDate, Date toDate) {

    Session session = sessionFactory.openSession();
    BigInteger sum;
    try{
        sum = (BigInteger)session
            .createSQLQuery(
                    "SELECT SUM(column) FROM table 
                     WHERE (column2 at time zone vas_tz()) >=:fromDate 
                   AND (column2 at time zone vas_tz()) < :toDate")
                  .setTimestamp("fromDate", fromDate)
                  .setTimestamp("toDate", toDate).uniqueResult();
    }catch (final HibernateException e){
        LOGGER.error(e.getMessage());
        throw new ProjectRuntimeException();
    }finally{
        session.close();

    }

编辑

DateUtils 来自package org.apache.commons.lang.time;

public static Date truncate(Date date, int field) {
    if (date == null) {
        throw new IllegalArgumentException("The date must not be null");
    }
    Calendar gval = Calendar.getInstance();
    gval.setTime(date);
    modify(gval, field, MODIFY_TRUNCATE);
    return gval.getTime();
}

当我说要返回我询问 Calendar 的日期的毫秒时,我的意思是如果日历提供了 8 月 7 日晚上 11:30 (因为我提供了时区),那么我希望毫秒来自8 月 7 日 11:30 之前的 Epoch 已针对该时区进行了调整。这是不正确的期望吗?

【问题讨论】:

标签: java date datetime


【解决方案1】:

我已经阅读了 Date 如何从 Epoch 返回 Millis,但我希望它会从我从日历中询问的日期的 Epoch 返回 Millis。

那么你的期望是不正确的——或者你没有清楚地表达你的期望。只有一个 Unix 纪元:它是午夜 UTCDate 没有时区的概念 - 只是自 Unix 纪元以来的毫秒数。

尚不清楚您的 DateUtils 类是什么,但任何声称将 Date 截断为一天而不指定时区的东西都有些可疑。

强烈建议您使用Joda Time 或Java 8 java.time 类-它们java.util.* 更易于使用。如果您必须使用java.util.Datejava.util.Calendar,则需要确定您感兴趣的时区,并适当地指定 - 使用Calendar,而不是Date - 当执行“truncate to day”等操作。

【讨论】:

  • 感谢您的意见。但是我需要了解我使用的代码有什么问题,因为这种日期/日历的使用在我继承的应用程序的许多地方重复出现,如果这部分有误,那么其他部分也会出错。
  • @idipous:您还没有向我们展示一半的代码(例如 DateUtils.truncate),所以我们无法帮助您纠正。我怀疑您需要非常仔细检查所有日期处理代码......理想情况下用 Joda 或 java.time 替换它。
  • @idipous:好的。好吧,您需要编写一个带时区的重载,并在日历上设置时区。否则将使用系统默认时区。
  • 所以你的意思是 Calendar gval = Calendar.getInstance(); 应该受到责备,对吧?我认为gval.setTime(date) 会解决这个问题,但日期又是 UTC 时代的毫秒数。那么它在那里做什么呢?它的作用是什么?
  • @idipous:我现在没时间回答。但请记住,日期是一个瞬间,而一天取决于时区。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-03
  • 2014-12-27
  • 2015-03-06
相关资源
最近更新 更多