繁体   English   中英

Oracle和Java中日期的日期差

[英]Date difference in date in Oracle and Java

以下问题困扰着我,我找不到任何合理的解释和解决方案。 也许有人可以启发我。

我有一个计算日期差(以天为单位)的应用程序-在搜索掩码和详细信息掩码中。 在第一个掩码中,我使用几天来筛选具有持续时间搜索条件的记录(“搜索掩码”),并使用SQL查询来执行此操作:

WHERE...
...
AND DECODE(TRUNC(to_number(SUBSTR((close_date - 
create_date),1,instr(close_date - create_date,' ')))), NULL, 
TRUNC(to_number(SUBSTR((systimestamp - create_date),1,instr(systimestamp - 
create_date,' ')))), TRUNC(to_number(SUBSTR((close_date - 
create_date),1,instr(close_date - create_date,' ')))) ) >=140

AND DECODE(TRUNC(to_number(SUBSTR((close_date - 
create_date),1,instr(close_date - create_date,' ')))), NULL, 
TRUNC(to_number(SUBSTR((systimestamp - create_date),1,instr(systimestamp - 
create_date,' ')))), TRUNC(to_number(SUBSTR((close_date - 
create_date),1,instr(close_date - create_date,' ')))) ) <=140

在这种特殊情况下,我尝试找出持续时间为140天的所有记录。

在第二个遮罩(详细信息)中,我显示记录详细信息,包括其持续时间。 这是通过以下Java代码完成的:

public static Integer getDuration(Date caseDate, Date closeDate) {
    Date beginDate = caseDate;
    Date endDate = (closeDate != null)? closeDate: new Date();

    long difference = endDate.getTime() - beginDate.getTime();   
    int daysDiff = (int) (difference / (24.0 * 60 * 60 * 1000));  
    return new Integer(daysDiff);
}

我的问题是,当我搜索时,会找到一些确实符合搜索条件的记录。 例如,我找到了4条记录,所有记录都有140天的持续时间。 根据Oracle的说法。 但是,当我为其中一些打开“详细信息”蒙版时,我得到的时间为139天。 因此,Java和Oracle以某种方式以不同的方式计算日期差。 似乎在Oracle中已经进行了一些四舍五入,但是我找不到发生这种情况的地方。 因此,任何建议都将有所帮助。 谢谢!

问候,阿拉迈克

日期可以相同,但时间可以不同。 毫秒计算结果为139天。 (java)

我建议不要使用毫秒,而是使用天数进行计算。

就像是

public long daysBetween(Calendar startDate, Calendar endDate) {
   Calendar date = (Calendar) startDate.clone();
   long daysBetween = 0;
   while (date.before(endDate)) {
      date.add(Calendar.DAY_OF_MONTH, 1);
      daysBetween++;
   }}

要么

/**
     *
     * @param c1 from
     * @param c2 to
     * @return amount of days between from and to
     */
    public int diff(Calendar c1, Calendar c2) {
        int years = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
        if (years == 0) {
            return c2.get(Calendar.DAY_OF_YEAR) - c1.get(Calendar.DAY_OF_YEAR);
        } else {
            Calendar endOfYear =  Calendar.getInstance();
            endOfYear.set(Calendar.YEAR, c1.get(Calendar.YEAR));
            endOfYear.set(Calendar.MONTH, 11);
            endOfYear.set(Calendar.DAY_OF_MONTH, 31);
            int days = endOfYear.get(Calendar.DAY_OF_YEAR) - c1.get(Calendar.DAY_OF_YEAR);
            for (int i=1;i <years;i++) {
                endOfYear.add(Calendar.YEAR, 1);
                days += endOfYear.get(Calendar.DAY_OF_YEAR);
            }
            days += c2.get(Calendar.DAY_OF_YEAR);
            return days;
        }
    }

旁注:第一个示例比第二个示例稍微慢一些,但是如果仅是很小的差异,则可以忽略。

我以相同的方式计算,但我使用dayDiff的时间不长于整数。 所以也尝试一下,不要抛弃它。 它应该工作正常。

这里的问题是,您认为这两个列都是DATE列,而这两个列中至少有一个确实是TIMESTAMP列。 从另一个日期中提取一个日期时,您会得到一个NUMBER。 但是,当您从时间戳记中提取日期时,反之亦然,则会得到一个INTERVAL。

一个例子

具有DATE和TIMESTAMP的表:

SQL> create table mytable (close_date,create_date)
  2  as
  3  select date '2010-11-01', systimestamp from dual union all
  4  select date '2010-11-11', systimestamp from dual union all
  5  select date '2010-12-01', systimestamp from dual
  6  /

Table created.

SQL> desc mytable
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 CLOSE_DATE                                         DATE
 CREATE_DATE                                        TIMESTAMP(6) WITH TIME ZONE

从DATE列中提取一个TIMESTAMP,导致一个INTERVAL:

SQL> select close_date - create_date
  2    from mytable
  3  /

CLOSE_DATE-CREATE_DATE
---------------------------------------------------------------------------
+000000130 11:20:11.672623
+000000140 11:20:11.672623
+000000160 11:20:11.672623

3 rows selected.

无需摆弄TO_NUMBER和SUBSTR。 只需使用EXTRACT函数从一个间隔中获取所需的组件:

SQL> select extract(day from (close_date - create_date))
  2    from mytable
  3  /

EXTRACT(DAYFROM(CLOSE_DATE-CREATE_DATE))
----------------------------------------
                                     130
                                     140
                                     160

3 rows selected.

问候,罗布。

这是一个带有两个TIMESTAMPS的示例,该示例显示INTERVAL被截断而不是四舍五入:

SQL> create table mytable (close_date,create_date)
  2  as
  3  select to_timestamp('2010-11-01','yyyy-mm-dd'), trunc(systimestamp,'dd') + interval '6' hour from dual union all
  4  select to_timestamp('2010-11-11','yyyy-mm-dd'), trunc(systimestamp,'dd') + interval '12' hour from dual union all
  5  select to_timestamp('2010-12-01','yyyy-mm-dd'), trunc(systimestamp,'dd') + interval '18' hour from dual
  6  /

Table created.

SQL> desc mytable
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 CLOSE_DATE                                         TIMESTAMP(9)
 CREATE_DATE                                        DATE

SQL> select close_date - create_date
  2    from mytable
  3  /

CLOSE_DATE-CREATE_DATE
---------------------------------------------------------------------------
+000000130 18:00:00.000000000
+000000140 12:00:00.000000000
+000000160 06:00:00.000000000

3 rows selected.

SQL> select extract(day from (close_date - create_date))
  2    from mytable
  3  /

EXTRACT(DAYFROM(CLOSE_DATE-CREATE_DATE))
----------------------------------------
                                     130
                                     140
                                     160

3 rows selected.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM